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.
Related
Trying to read data of specific envelopes from DocuSign using completely backend java process ... and after some trial and error I've obtained AccessToken with JWT grant but still getting authorization error when asking for actual data :(
Defined new integration key 9xxx7e
User Application: Authorization Code Grant
No secrets added
Service Integration - uploaded public RSA key
Added one Redirect URI (regardless I don't need any)
Manual confirmation of corresponding link : https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=9xxx7e&state=123&redirect_uri=https://my.redirect.net/DocuSign ... assuming it is just one-time action
Successfully requested Access Token using java code (using com.docusign:docusign-esign-java:3.10.1)
ApiClient = new ApiClient(ApiClient.DEMO_REST_BASEPATH);
OAuthToken token = apiClient.requestJWTApplicationToken(integrationKeyJwt, scopes, privateKeyFileContent, 3600);
Trying to get envelope data using simple HttpGet
HttpGet request = new HttpGet("https://demo.docusign.net/restapi/v2.1/accounts/6xxx1e/envelopes");
request.addHeader("Content-Type", "application/json");
request.addHeader("Authorization", "Bearer " + token.getAccessToken());
but still got 401 response with content:
{"errorCode":"AUTHORIZATION_INVALID_TOKEN","message":"The access token provided is expired, revoked or malformed. Authentication for System Application failed."}
Please any idea what is wrong? How to obtain correct Access Token?
P.S.: I also tried to get Authorization Code Grant without JWT or implicit grant but no luck without browser tough :(
I would recommend that you print the accessToken you're creating in a file and use in Postman. This will at least help you narrow it down to either the Token generation step or sending the request portion.
Let us know what you find.
Problem was/is with use of apiClient.requestJWTApplicationToken but apiClient.requestJWTUserToken is the way to go
We are trying to use Google OAuth in our product. The flow would be to get Client get the auth from the users and send the token to server. On server side I need to verify the token is valid. For now, I am using OAuth2Sample provided by Google as client. when I verify the sent token on server side, I am getting the following exception:
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_grant",
"error_description" : "Malformed auth code."
}
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest.execute(GoogleAuthorizationCodeTokenRequest.java:158)
Here is the code on the server side:
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
"https://www.googleapis.com/oauth2/v4/token",
CLIENT_ID,
CLIENT_SECRET,
authToken, //Sent from the client
"") // specify an empty string if you do not have redirect URL
.execute();
Here is how I get the accesstoken on the client side:
private static final List<String> SCOPES = Arrays.asList(
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email");
//...
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, JSON_FACTORY,
clientSecrets, //Client ID and Client Secret
SCOPES).setDataStoreFactory(
dataStoreFactory).build();
LocalServerReceiver lsr = new LocalServerReceiver();
Credential cr = new AuthorizationCodeInstalledApp(flow, lsr).authorize("user");
return cr.getAccessToken(); //send this to server for verification
The token is not corrupted on the way to server and it is:
ya29.Glx_BUjV_zIiDzq0oYMqoXkxz8VGzt8GCQuBiaaJ3FxN0qaLxbBXvnWXjNKZbpeu4jraoEqw6Mj9D7LpTx_8Ts_8TH0VGT5cbrooGcAOF0wKMc1DDEjm6p5m-MvtFA
If I try to access profile and email from the client side, it works fine. Same token does not work on the server side gets malformed token exception.
I am using Node.js googleapis client library, Here is my case:
The authorization code in the url hash fragment is encoded by encodeURIComponent api, so if you pass this code to request access token. It will throw an error:
{ "error": "invalid_grant", "error_description": "Malformed auth code." }
So I use decodeURIComponent to decode the authorization code.
decodeURIComponent('4%2F_QCXwy-PG5Ub_JTiL7ULaCVb6K-Jsv45c7TPqPsG2-sCPYMTseEtqHWcU_ynqWQJB3Vuw5Ad1etoWqNPBaGvGHY')
After decode, the authorization code is:
"4/_QCXwy-PG5Ub_JTiL7ULaCVb6K-Jsv45c7TPqPsG2-sCPYMTseEtqHWcU_ynqWQJB3Vuw5Ad1etoWqNPBaGvGHY"
In Java, maybe you can use URLDecoder.decode handle the code.
For anyone who might face this in the future. I faced this issue and decodeURIComponent did not work with me. The previous answers work with for different issue.
From the question itself, you can see that the token starts with ya29.
ya29.Glx_BUjV_zIiDzq0oYMqoXkxz8VGzt8GCQuBiaaJ3FxN0qaLxbBXvnWXjNKZbpeu4jraoEqw6Mj9D7LpTx_8Ts_8TH0VGT5cbrooGcAOF0wKMc1DDEjm6p5m-MvtFA
That indicates that the token is an online token. In case of the online login, you can see that the response looks like this
But that will not work with server side login. So, when using some Google client library, please note that there are two variables that you need to check:
access_type: offline
responseType: code
Once you configure Google client library with those fields, you can see that the response of the login will change to something like this
{
"code": "4/0AX4XfWgaJJc3bsUYZugm5-Y5lPu3muSfUqCrpY5KZoGEGAHuw0jrkg_xkD_RX-6bNUq-vA"
}
Then you can send that code to the backend and it will work.
Thanks to slideshowp2's answer, and Subhadeep Banerjee's comment.
I am using server-side web app with HTTP/REST ,also facing the same problem
and yes, the reason is that authorization code return from URL is encoded.
After decode, everything work fine to get access token.
p.s. here is some info about encodedURL
since our Content-Type: application/x-www-form-urlencoded
we do get this error when for some reason the call back url of the auth is called a second time. The first time it works but the second time it errors out.
Not sure how the users are able to do that. Maybe by pressing the back button in the browser.
The error is indeed this:
{"error": "invalid_grant","error_description": "Malformed auth code."}
Encoding the code in the call back URL was not the problem.
I get a valid code on the client side login of my application using angularJS Oauth Module GAuth.checkAuth(). and then GAuth.getToken().
The code is valid only for 1 hour and any API like GoogleDocs,Gmail accessed after 1 hour fails and needs relogin.
To overcome this I am trying to send the code to the server for getting AccessCode at Server so that I can send same with requests to GoogleDocs, Gmail etc
GoogleAuthorizationCodeTokenRequest req =
new GoogleAuthorizationCodeTokenRequest(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
"https://www.googleapis.com/oauth2/v4/token",
// "https://accounts.google.com/o/oauth2/token",
"901142925530-21ia7dqnsdsdsndnsnnnfdc9cm2u07.apps.googleusercontent.com",
"6NSvw0efghyuuG8YGOBWPln79n",
authCode,
"http://localhost:8080");
req.setGrantType("authorization_code");
//req.put("refresh_token", authCode);
//req.put("access_type", "offline");
GoogleTokenResponse tokenResponse =
req.execute();
tokenResponse.getAccessToken()
Where authCode is the code I received in GAuth Token
But the call is failing and in response I get
400 Bad Request
{
"error" : "invalid_grant",
"error_description" : "Incorrect token type."
}
Any help is highly appreciated!
When the user first authenticates your application you are given an authorization code. You then need to take this authorization code and exchange it for an access token and a refresh token. Once the authorization code has been used it can not be used again.
grant_type=authorization_code
Denotes that you are asking Google to verifiy that your authorization code and give you a new access token and refresh token.
It sound to me like you are taking either the access token returned from that request and sending it to grant_type=authorization_code end point which is not going to work its the wrong type of code. hens the error you are getting of
400 Bad Request { "error" : "invalid_grant", "error_description" : "Incorrect token type." }
You will need to take the refresh token you are given. If there is one I am not sure that you can even get a refresh token from AngularJs. You can get one using java though.
A refresh of an access token in pure rest will look like this
https://accounts.google.com/o/oauth2/token
client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&refresh_token=1/ffYmfI0sjR54Ft9oupubLzrJhD1hZS5tWQcyAvNECCA&grant_type=refresh_token
Note the &grant_type=refresh_token. If you are using the Google api java client library it should handle all of that for you. However your tagging is a little confusing its unclear if you are trying to do this in java or angularjs which I do not believe will allow you to use refresh tokens. Again I am not an angular dev I could be wrong on that point.
Anwser:
You the code you are sending is not an authorization code. Only an authorization code can be sent to grant_type=authorization_code. Solution: Send an authorization_code
Types of Google codes and tokens:
There are three types of codes or tokens you should be aware of with Oauth2.
Authorization code.
Refresh token
Access token
When you request access of a user and they grant your application access you are given an Authorization code. The Authorization code is short lived it probably less then 10 minutes and it can only be used once.
The Authorization code is used to get the initial access token and the refresh token from googles authentication server. by using the grant_type=authorization_code
Access token are good for about an hour. They are used to make calls to google APIs
https://www.googleapis.com/plus/v1/people/me?access_token={your access token}
You can use the access token as often as you want during that hour assuming you don't blow out some quota.
Refresh tokens are used to request a new access token from the Google authentication server when the access token you have current has expired or you just want a new one. here the grant_type=refresh_token is used to request a new access token you are essentially telling google I am sending you a refresh token you know what to do.
additional reading
I have a coupe of tutorials that might help you out Google 3 Legged OAuth2 Flow and Google Developer Console Oauth2 credentials
Also helpful when learning Oauth: The OAuth 2.0 Authorization Framework
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.
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.