How to get Access Token in java using OAuth 1.0? - java

Requirement: I want to access resources reside in cloud application.
This cloud application provided me following details to access resources through OAuth 1.0 authentication.
OAuth Credentials
Consumer Key
Consumer Secret
OAuth Request URLs
1. Request Token URL
2. Authorise URL
3. Access Token URL
4. API Endpoint URL
I have wrote following java code to get Request Token and Request Token Secret . I store Request Token and Secret in property file for retrieving Access Token.
OAuthAccessor accessor = createOAuthAccessor();
OAuthClient client = new OAuthClient(new HttpClient4());
client.getRequestToken(accessor);
props.setProperty("requestToken", accessor.requestToken);
props.setProperty("tokenSecret", accessor.tokenSecret);
private OAuthAccessor createOAuthAccessor(){
String consumerKey = props.getProperty("consumerKey");
String callbackUrl = null;
String consumerSecret = props.getProperty("consumerSecret");
String reqUrl = props.getProperty("requestUrl");
String authzUrl = props.getProperty("authorizationUrl");
String accessUrl = props.getProperty("accessUrl");
OAuthServiceProvider provider
= new OAuthServiceProvider(reqUrl, authzUrl, accessUrl);
OAuthConsumer consumer
= new OAuthConsumer(callbackUrl, consumerKey,
consumerSecret, provider);
return new OAuthAccessor(consumer);
}
Property file details:
requestToken= generated by service provider
authorizationUrl= Authorise URL provided by cloud application
consumerSecret= Consumer Secret provided by cloud application
accessUrl=Access Token URL provided by cloud application
tokenSecret= generated by service provider
requestUrl= Request Token URL provided by cloud application
consumerKey= Consumer Secret provided by cloud application
appName= API Endpoint URL provided by cloud application
I am able to retrieve Request Token and Request Token Secrete from Service Provider with Request Token URL provided by cloud application.
Then I used generated Request Token and Request Token Secrete to get Access Token by using following code
OAuthAccessor accessor = createOAuthAccessor();
accessor.tokenSecret = props.getProperty("tokenSecret");
OAuthClient client = new OAuthClient(new HttpClient4());
return client.invoke(accessor, "GET", url, params);
After executing above code for retrieving Access token I got following exception
If I pass API Endpoint URL /Resource as value of URL parameter to client.invoke() in above code then I am getting following exception
> <<<<<<<< HTTP response: HTTP/1.1 401 Unauthorized Cache-Control:
> private Content-Type: text/html; charset=utf-8 WWW-Authenticate: OAuth
> Realm="115.248.52.162" X-S: 445759-O1VMAP02 Strict-Transport-Security:
> max-age=31536000 Date: Tue, 18 Jun 2013 06:59:28 GMT Content-Length:
> 142
>
> Exception in thread "main" net.oauth.OAuthProblemException:
> token_rejected oauth_problem_advice: Token RZXHZYCCUMNMZA88032WJFB
> does not match an expected ACCESS token
And if I pass Access Token URL as value of URL parameter in client.invoke() then I am getting following exception
> <<<<<<<< HTTP response: HTTP/1.1 401 Unauthorized Cache-Control:
> private Content-Type: text/html; charset=utf-8 WWW-Authenticate: OAuth
> Realm="49.248.38.202" X-S: 445758-O1VMAP01 Strict-Transport-Security:
> max-age=31536000 Date: Tue, 18 Jun 2013 05:47:30 GMT Content-Length:
> 115
>
> oauth_problem=permission_denied&oauth_problem_advice=The%20consumer%20was%20denied%20access%20to%20this%20resource.
Questions:
Which URL Should I use to get Access Token?
Am I missing any step or setting to retrieve Access token?
Thanks in Advance.

Here is the java code to generate access token. I have integrated my generic application to Jira using OAuth Authentication. Here is the java code to access the using OAuth Authentication. Please include rest-oauth-client-1.0.one-jar jar in your application.
public static String getAccessToken(){
final String baseURI = "http://bmh1060149:8080";
final String consumerKey = "hardcoded-consumer";
final String consumerPrivatekey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDFkPMZQaTqsSXI+bSI65rSVaDzic6WFA3WCZMVMi7lYXJAUdkXo4DgdfvEBO21Bno3bXIoxqS411G8S53I39yhSp7z2vcB76uQQifi0LEaklZfbTnFUXcKCyfwgKPp0tQVA+JZei6hnscbSw8qEItdc69ReZ6SK+3LHhvFUUP1nLhJDsgdPHRXSllgZzqvWAXQupGYZVANpBJuK+KAfiaVXCgA71N9xx/5XTSFi5K+e1T4HVnKAzDasAUt7Mmad+1PE+56Gpa73FLk1Ww+xaAEvss6LehjyWHM5iNswoNYzrNS2k6ZYkDnZxUlbrPDELETbz/n3YgBHGUlyrXi2PBjAgMBAAECggEAAtMctqq6meRofuQbEa4Uq5cv0uuQeZLV086VPMNX6k2nXYYODYl36T2mmNndMC5khvBYpn6Ykk/5yjBmlB2nQOMZPLFPwMZVdJ2Nhm+naJLZC0o7fje49PrN2mFsdoZeI+LHVLIrgoILpLdBAz/zTiW+RvLvMnXQU4wdp4eO6i8J/Jwh0AY8rWsAGkk1mdZDwklPZZiwR3z+DDsDwPxFs8z6cE5rWJd2c/fhAQrHwOXyrQPsGyLHTOqS3BkjtEZrKRUlfdgV76VlThwrE5pAWuO0GPyfK/XCklwcNS1a5XxCOq3uUogWRhCsqUX6pYfAVS6xzX56MGDndQVlp7U5uQKBgQDyTDwhsNTWlmr++FyYrc6liSF9NEMBNDubrfLJH1kaOp590bE8fu3BG0UlkVcueUr05e33Kx1DMSFW72lR4dht1jruWsbFp6LlT3SUtyW2kcSet3fC8gySs2r6NncsZ2XFPoxTkalKpQ1atGoBe3XIKeT8RDZtgoLztQy7/7yANQKBgQDQvSHEKS5SttoFFf4YkUh2QmNX5m7XaDlTLB/3xjnlz8NWOweK1aVysb4t2Tct/SR4ZZ/qZDBlaaj4X9h9nlxxIMoXEyX6Ilc4tyCWBXxn6HFMSa/Rrq662Vzz228cPvW2XGOQWdj7IqwKO9cXgJkI5W84YtMtYrTPLDSjhfpxNwKBgGVCoPq/iSOpN0wZhbE1KiCaP8mwlrQhHSxBtS6CkF1a1DPm97g9n6VNfUdnB1Vf0YipsxrSBOe416MaaRyUUzwMBRLqExo1pelJnIIuTG+RWeeu6zkoqUKCAxpQuttu1uRo8IJYZLTSZ9NZhNfbveyKPa2D4G9B1PJ+3rSO+ztlAoGAZNRHQEMILkpHLBfAgsuC7iUJacdUmVauAiAZXQ1yoDDo0Xl4HjcvUSTMkccQIXXbLREh2w4EVqhgR4G8yIk7bCYDmHvWZ2o5KZtD8VO7EVI1kD0z4Zx4qKcggGbp2AINnMYqDetopX7NDbB0KNUklyiEvf72tUCtyDk5QBgSrqcCgYEAnlg3ByRd/qTFz/darZi9ehT68Cq0CS7/B9YvfnF7YKTAv6J2Hd/i9jGKcc27x6IMi0vf7zrqCyTMq56omiLdu941oWfsOnwffWRBInvrUWTj6yGHOYUtg2z4xESUoFYDeWwe/vX6TugL3oXSX3Sy3KWGlJhn/OmsN2fgajHRip0=";
AtlassianOAuthClient jiraoAuthClient = new AtlassianOAuthClient(consumerKey, consumerPrivatekey, baseURI, "");
TokenSecretVerifierHolder requestToken = jiraoAuthClient.getRequestToken();
String authorizeUrl = jiraoAuthClient.getAuthorizeUrlForToken(requestToken.token);
String token = requestToken.token;
String tokenSecret = requestToken.secret;
System.out.println("Token is " + requestToken.token);
System.out.println("Token secret is " + requestToken.secret);
System.out.println("Retrieved request token. go to " + authorizeUrl);
The above code will give you token, tokenSecret and authorizeUrl. After getting the authorizeUrl, Paste the URL in the browser it will ask for allow and deny options. Allow it to generate the verification code. Ather the url is authorized the access token can be generated from the code below.
URI uri=null;
try {
uri = new URI(authorizeUrl);
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(Desktop.isDesktopSupported()){
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(uri);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
String verifier = requestToken.verifier;
String accessToken = jiraoAuthClient.swapRequestTokenForAccessToken(token, tokenSecret, verifier);
System.out.println("Access token is : " + accessToken);
return accessToken;
}
If you are also interested in accessing OAuth via command prompt you can also access it via there also. Here are the steps to access it via command prompt.
First create an application link. For that you can refer https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-oauth-authentication
Download rest-oauth-client-1.0.one-jar.jar and rest-oauth-client-1.0-sources.jar and paste in your local drive. Access the following commands from there.
D:\OAuth Jars>java -jar rest-oauth-client-1.0.one-jar.jar requestToken "Your Jira base url"
Once you execute the above command you will get the Token, Token secret and Retrieved request token.
Token is iJKs7Sq4nI3tK0bTqBYSNNOt9rkwrKK9
Token secret is qimK5FibcAKD5ACbF2aKEPpiBWltgwET
Retrieved request token. go to http://bmh1060149:8080/plugins/servlet/oauth/authorize?oauth_token=iJKs7Sq4nI3tK0bTqBYSNNOt9rkwrKK9
Then you have to invoke the Retrieved request token url through the browser to get the verification code. It will ask you to allow or deny. If you click on allow it will give you verification code.
D:\OAuth Jars>java -jar rest-oauth-client-1.0.one-jar.jar accessToken "Your Jira base url" "iJKs7Sq4nI3tK0bTqBYSNNOt9rkwrKK9" "qimK5FibcAKD5ACbF2aKEPpiBWltgwET" "toYvZB"
This will give you the access token
Access token is : zGBqUzmwobyS0GFXrJMIs18lsAUd51Wb
Once you get the access token you can fetch the data from whatever url you will pass to it.
D:\OAuth Jars>java -jar rest-oauth-client-1.0.one-jar.jar request "zGBqUzmwobyS0GFXrJMIs18lsAUd51Wb" "Your Jira base url/rest/api/2/issue/NWFM-4"
Hope this helps

Without seeing your cloud api documentation, I can only assume they follow the typical oauth dance for authentication - which is:
you get request token from provider (request token url)
using request token, form an auth url (usually points to provider)
redirect user to auth url (authorize url)
user authenticates/authorizes
provider does callback back to you with verifier
using verifier and request token, you exchange for access token (access token url)
now you can use your access token to access the api
So unless you're missing some of these steps, some other things to look at are: correctly signing request, using correct urls for each step, passing correct token at each step.
Also, the request token/secret is usually short lived, while the access token is "usually" much longer and in most cases/systems can be used with multiple api request.

Related

Getting 401 when signing HTTP message with signpost

I am integrating my web app with AppDirect,
for this I created a java rs API using jersey.
When I subscribe to an event, I get a map containing the oauth values (key and secret) to sign my request and an event url to which I issue a sign fetch to.
I am getting those values (oauth and eventurl) as expected.
Now when I try to issue a signed fetch using the library signpost, I use the following code:
OAuthConsumer consumer = new DefaultOAuthConsumer(consumer_key, secret);
// create an HTTP request to a protected resource
URL url = new URL(eventUrl);
HttpURLConnection request = (HttpURLConnection) url.openConnection();
// sign the request
consumer.sign(request);
// send the request
request.connect();
I get this error message:
getResponseMessage: Unauthorized
getresponsecode: 401
I also tried with the following test values:
url = "https://www.appdirect.com/api/integration/v1/events/dummyOrder";
dummyKey = "Dummy";
dummySecret = "secret";
But I got the same result.
Please how can I fix it?
I also tried and adding this:
request.setRequestMethod("GET");
request.setRequestProperty("Authorization", "OAuth");
request.setRequestProperty("Host", "...");
request.setRequestProperty("Content-Type", "application/xml");
request.setRequestProperty("oauth_nonce", oauth_nonce);
request.setRequestProperty("oauth_signature", oauth_signature);
request.setRequestProperty("oauth_signature_method", oauth_signature_method);
request.setRequestProperty("oauth_timestamp", oauth_timestamp);
request.setRequestProperty("oauth_version", oauth_version);
also tried with key:secret in the Authorization property
Here is a behavior of this service when testing via Postman Chrome extension.
If you are using OAuth provider, so you need to get valid api-key for AppDirect and secret.
BTW second screenshot shows you don't need to send an OAuth token to appdirect to https://www.appdirect.com/api/integration/v1/events/dummyOrder, because it authorizes any url.
So, according to your notes, you have to add proper(secret and key) and then AppDirect OAuth server will return you a valid token which you will use when addressing AppDirect's repositories. Or you may send key-secret with each request.

Getting 401-Unauthorized while getting photo using outlook REST API - java cliet

I am trying to retrieve user photo using outlook REST API(https://msdn.microsoft.com/en-us/office/office365/api/photo-rest-operations#UserphotooperationsGetphoto)
I got the access token following (https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx)
but getting this error : any help?
HTTP/1.1 401 Unauthorized [Content-Length: 0, Server: Microsoft-IIS/8.0, request-id: 6925fcab-9021-4059-af4b-4cbf130faea7, X-CalculatedBETarget: CY1PR0401MB1388.namprd04.prod.outlook.com, X-BackEndHttpStatus: 401, Set-Cookie: exchangecookie=87cb2447eae9401c80a96c497dff06a9; expires=Sat, 22-Apr-2017 07:56:53 GMT; path=/; HttpOnly, x-ms-diagnostics: 2000001;reason="The access token is acquired using an authentication method that is too weak to allow access for this application. Presented auth strength was 1, required is 2.";error_category="invalid_token",
code looks something like this:
HttpClient httpclient = HttpClients.createDefault();
final String bearerToken = getBearerToken();
HttpGet request = new HttpGet("https://outlook.office.com/api/v2.0/me/photo/$value");
request.setHeader(javax.ws.rs.core.HttpHeaders.AUTHORIZATION, "Bearer " + bearerToken);
request.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
HttpResponse response = httpclient.execute(request);
return IOUtils.toByteArray(response.getEntity().getContent());
According to the error message. Instead of a client_secret in your request body, you need a client_assertion.
For more details, you can reference the blog Building Daemon or Service Apps with Office 365 Mail, Calendar, and Contacts APIs (OAuth2 client credential flow)
According to the API you call "https://outlook.office.com/api/v2.0/me/photo/$value". It seems that you only want to get the photo for the current login user; if so, you can use Authorization Code Grant Flow to get the token which will not require the client certificates.
UPDATE#1:
Can this be done programmatically/API way
As far as I know, the consent need the user's or admin's interactivity.
https://login.windows.net/common/oauth2/authorize?response_type=code&client_id={0}&resource={1}&redirect_uri={2}&prompt={3}
If you are developing a ASP.NET web application, you can reference the sample project O365-WebApp-MultiTenant.
BTW, when calling the API with app-token, you need to specify the user name.
e.g.
https://outlook.office.com/api/v2.0/users('user1#customdomain.onmicrosoft.com')/messages
UPDATE#2:
The 403 code when updating the photo using the app token is expected result.
As we can see from the figure above, updating the user photo requires the delegated permission "User.Read.Write". The app token does not have permission to update user's photo.

How to sign the request with the OAuth signature method for HMAC-SHA1 encryption

We're trying to connect with another company's custom API which uses two-legged OAuth to authenticate a request and send us a response.
At the moment the code we have is sending a request but it's not being authenticated at the other end and so sending a UNAUTHORISED response.
As said by other company the authentication include below steps.
"Authentication is handled using two-legged OAuth authentication:
All requests must include both an oauth_consumer_key and an oauth_signature attribute submitted via the HTTP GET method.
The oauth_consumer_key attribute will be the user name that the user uses to access our web site.
The oauth_signature attribute is obtained by signing the request with the OAuth signature method for HMAC-SHA1 encryption. The signature is generated using both the oauth_consumer_key attribute and the consumer secret. A single consumer secret is required per franchise and can be obtained upon request from test#examplerelationships.com.
OAuth libraries are available for many languages here: http://oauth.net/code/."
what we tried at our end using Scribe java library is below
public static void main(String[] args){
String oauth_consumer_key = "test#example.com";
String oauth_signature = "keyprovided";
OAuthService service = new ServiceBuilder()
.provider(Dummy.class)
.apiKey(oauth_consumer_key)
.apiSecret(oauth_signature)
.build();
OAuthRequest request = new OAuthRequest(Verb.GET,"https://example.com/api/users");
Token accessToken = new Token("","");
service.signRequest(accessToken, request);
Response response = request.send();
System.out.println(response.getHeaders());
System.out.println(response.getBody());
}
The response currently is 401-Unauthorized. What else can be missing? And what about HMAC-SHA1 encryption. I have got a little idea about oauth.

restFB: Facebook login redirect

i've tried to request
https://graph.facebook.com/oauth/authorize?client_id=MY_API_KEY& redirect_uri=http://www.facebook.com/connect/login_success.html&scope=publish_stream,create_event
but i'm getting an error after redirection:
"The requested URL /login.php?login_attempt=1&next=https%3A%2F%2Fwww.facebook...."
where did login.php come from, that is not the redirection page?!
what is the problem at redirection?
thanks!
The redirect_uri should be a URL on your server where facebook will redirect the user after he/she granted you access to his/her protected resources. There you should exchange the request token--the value of the code querystring parameter returned from facebook--for the access_token with a server-side fetch.
The redirect_uri must be on the same domain as the Site URL setting on the Website with Facebook Login in the facebook application setting at https://developers.facebook.com/apps/{your-app-id}/summary/
Redirect the user to the provider
Redirect the user to the provider so he/she can tell the provider that he/she is giving you access to his/hers protected resources which you specified in the scope. After the user gives consent or rejects, the provider will redirect the user to the redirect_uri on your server. To prevent cross site scripting request forgery, you should generate and store a CSRF token and send it with the request.
https://www.facebook.com/dialog/oauth?
client_id={your-app-id}&
redirect_uri=http://your-site.com/after-redirect&
scope=list,of,scopes&
state={a-hard-to-guess-random-csrf-token}
Exchange the request token (code) for access token
In the request handler at http://your-site.com/after-redirect you should check the error and error_message request params. If there are no errors, you should first validate (compare with the stored one) the state CSRF token and if valid, then exchange the code (request token) for an access token by the provider with a server-side fetch. The redirect_uri and grant_type=authorization_code params are required (at least by some providers).
https://graph.facebook.com/oauth/access_token?
code={request-token}&
client_id={your-app-id}&
client_secret={your-app-secret}&
redirect_uri=http://your-site.com/after-redirect&
grant_type=authorization_code
Use the access token to access the user's protected resources
If the token type is bearer you should sent the access_token in the HTTP headers in the form of Authorization: Bearer {access-token}'. See: https://www.rfc-editor.org/rfc/rfc6750#section-2.1
https://graph.facebook.com/me?
fields=name,birthday,photos.limit(10).fields(id, picture)&
access_token={access-token}
Try this way :
public String getOauthUrl(String clientId, String callbackUrl, String scope) {
return "https://graph.facebook.com/oauth/authorize?client_id="
+ clientId + "&display=page&redirect_uri="
+ callbackUrl + "&scope=" + scope;
}
this is the code i'm using:
URL url2 = new URL("https://www.facebook.com/dialog/oauth?client_id=MY_APP_ID&redirect_uri=https://www.facebook.com/connect/login_success.html&scope=publish_stream,create_event");
URLConnection conn = url2.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String test;
test=rd.readLine();
resp.getWriter().println(test);
rd.close();

troubleshooting scribe for social api authentication

I just started looking at scribe for authentication with social networks such as twitter/facebook etc. I am using the example for twitter as reference. However, I don't seem to get oauth_verifier from twitter for some reason (even though the callback is registered through the service builder - I am using localhost in the callback as it worked with another social api). Any helpful suggestions would be quite welcome. thanks in advance.
OAuthService service = new ServiceBuilder()
.provider(TwitterApi.class)
.apiKey(consumerKey)
.apiSecret(consumerSecret)
.callback("http://localhost/oauth/twitter")
.build();
//get the token
Token requestToken = service.getRequestToken();
String authUrl = service.getAuthorizationUrl(requestToken);
Logger.info("authurl::" + authUrl); // not getting the oauth_verifier
Debug output from scribe (I changed the token info):
setting oauth_callback to http://localhost/oauth/twitter
generating signature...
base string is: POST&http%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Flocalhost%252Foauth%252Ftwitter%26oauth_consumer_key%3DAAACCCV6ASDFGHJCgYBCD%26oauth_nonce%3D607134093%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1353965859%26oauth_version%3D1.0
signature is: +mSqKJIC1Q0pMEFs/gIJViF7kbg=
appended additional OAuth parameters: { oauth_callback -> http://localhost/oauth/twitter , oauth_signature -> +mSqKJIC1Q0pMEFs/gIJViF7kbg= , oauth_version -> 1.0 , oauth_nonce -> 607134093 , oauth_signature_method -> HMAC-SHA1 , oauth_consumer_key -> AAACCCV6ASDFGHJCgYBCD , oauth_timestamp -> 1353965859 }
using Http Header signature
sending request...
response status code: 200
response body: oauth_token=itJrpOP3KLeD7Ha6oy0IRr4HysFut5eAOpIlj8OmNE&oauth_token_secret=X8LmhAUpvIkfEd7t7P1lvwwobC3JJIhUabcEs0Rn5w&oauth_callback_confirmed=true
authurl::https://api.twitter.com/oauth/authorize?oauth_token=itJrpOP3KLeD7Ha6oy0IRr4HysFut5eAOpIlj8OmNE
obtaining access token from http://api.twitter.com/oauth/access_token
setting token to: Token[itJrpOP3KLeD7Ha6oy0IRr4HysFut5eAOpIlj8OmNE , X8LmhAUpvIkfEd7t7P1lvwwobC3JJIhUabcEs0Rn5w] and verifier to: org.scribe.model.Verifier#55ac8c3d
generating signature...
Update:
I am able to receive the oauth_verifier now. I will update this post once I am done testing.
pilot error mostly. I was able to get oauth working with twitter using scribe. After getting the service, the request Token from the service & then the authorizationUrl from the service (while passing in the request token), I was able to redirect to the authorization URL. Once there, I was able to authenticate myself against twitter using my twitter ID which redirected me to the callback URL specified when I created the service. Upon authentication, I received the oauth_verifier which I was able to use to create the verifier & then receive the access token from the service using the verifier and the request token. Then the oauth request was made & signed which resulted in the response from twitter with the user details. Worked. Hope it helps.

Categories

Resources