My question is about OAuth2 access token response from Linkedin api. When I'm trying to get this token I recieve the following response:
{"access_token":"...","expires_in":...}
But the thing is that according to OAuth2 documentation (in 5.1 paragraph) there should be at least one more required parameter - "token_type".
So the question is: could it be somehow customized so the linkedin API will return this parameter with access token response or it is just a departure from the rule and this parameter won't be returned?
Thanks in advance.
I have run into the same issue. According to LinkedIn Docs:
A successful Access Token request will return a JSON object containing the following fields:
access_token — The access token for the user. This value must be kept secure, as per your agreement to the API Terms of Use.
expires_in — The number of seconds remaining, from the time it was requested, before the token will expire. Currently, all access tokens are issued with a 60 day lifespan.
they respond with
{"access_token":"...","expires_in":...}
which violates the standard.
Currently I am using Spring Security 5.0.3 and to fix the issue, I had to monkeypatch one class:
com.nimbusds.oauth2.sdk.token.BearerAccessToken
I will not post the whole class, only a significant part:
public static BearerAccessToken parse(final JSONObject jsonObject)
throws ParseException {
// Parse and verify type
AccessTokenType tokenType;
try {
tokenType = new AccessTokenType(JSONObjectUtils.getString(jsonObject, "token_type"));
} catch (ParseException ex) {
tokenType = AccessTokenType.BEARER;
}
if (!tokenType.equals(AccessTokenType.BEARER))
throw new ParseException("Token type must be \"Bearer\"");
//...
}
I hoped to get answer from Linkedin member since they stated on their site that stackoverflow is a proper place for asking such questions. But since there is no answer from them and I didn't find any relevant information regarding this question I believe that it is just the way they implemented OAuth 2.0 protocol.
Related
I am trying to generate access token for twilio chat but got this error:I have been trying to figure out where the error is coming from but can't get it figured out. I will really appreciate your help. Thanks
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.zihron.projectmanagementapp, PID: 16355
java.lang.Error: javax.xml.datatype.DatatypeConfigurationException: Provider org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl not found
at javax.xml.bind.DatatypeConverterImpl.<clinit>(DatatypeConverterImpl.java:744)
at javax.xml.bind.DatatypeConverter.<clinit>(DatatypeConverter.java:78)
at javax.xml.bind.DatatypeConverter.printBase64Binary(DatatypeConverter.java:547)
at io.jsonwebtoken.impl.Base64Codec.encode(Base64Codec.java:24)
at io.jsonwebtoken.impl.Base64UrlCodec.encode(Base64UrlCodec.java:22)
at
io.jsonwebtoken.impl.AbstractTextCodec.encode(AbstractTextCodec.java:31)
at io.jsonwebtoken.impl.DefaultJwtBuilder.base64UrlEncode(DefaultJwtBuilder.java:314)
at io.jsonwebtoken.impl.DefaultJwtBuilder.compact(DefaultJwtBuilder.java:282)
at com.twilio.jwt.Jwt.toJwt(Jwt.java:100)
at ZihronChatApp.token.TokenGenerator.getToken(TokenGenerator.java:34)
at com.zihron.projectmanagementapp.ChatActivity.onCreateView(ChatActivity.java:43)
I have my details below:
public AccessToken getToken() {
// Required for all types of tokens
String twilioAccountSid ="AC601f2c7***7ed***640***264c***d0d";
String twilioApiKey = "SK684***dda***c81****6c4a****093**";
String twilioApiSecret ="96****dbc06****b74d50***b9***3*4";
String serviceSid="IS***a29****e24****5d****4b20**3e*";
String identity = "joshua.hamilton#gmail.com";
ChatGrant grant = new ChatGrant();
grant.setServiceSid(serviceSid);
AccessToken token = new AccessToken.Builder(twilioAccountSid,
twilioApiKey, twilioApiSecret)
.identity(identity).grant(grant).build();
Log.e("++==--",""+token.toJwt());
//.identity(identity).grant(grant);
return token;
}
Twilio developer evangelist here.
The Twilio Java library is not intended for use within Android projects.
The issue here is that you should not be storing your credentials within your application. A malicious user could decompile your application, take your credentials and abuse them.
Instead, you should create a server (or use some sort of serverless environment, like Twilio Functions) that can run this code and return the token. You should then make an HTTP request from your Android application to fetch that token. Check out the Twilio Programmable Chat Android Quickstart to see how it's done there.
We have the following steps to authenticate with Office 365 and get the access tokens required to request calendar events...
Send the user to https://login.microsoftonline.com/common/oauth2/authorize?response_type=code , passing the client id and a redirect URL
The user logs in and is redirected back to the redirect URL with a ?code= query string value
Make an API request to https://login.microsoftonline.com/common/oauth2/token to get a token for the https://api.office.com/discovery/ resource, passing the code that we got in step 2
Store the access token and refresh token which is returned
Make an API request to https://api.office.com/discovery/v2.0/me/services to get a list of end points that we have access to
For the end point that I want to work with (Office 365 Exchange) , make an API request to https://login.microsoftonline.com/common/oauth2/token to get a token for the https://outlook.office365.com/ resource, passing the code that we got in step 2
Store the access token and refresh token which is returned
Use the access token from step 7 to fetch calendar events
This used to work fine, but today I'm getting a different result from the API call on step 6
I used to get an access token and refresh token which I could use for the outlook.office365.com resource, but now I'm getting an error message like the following...
{
"error":"invalid_grant",
"error_description":"AADSTS70002: Error validating credentials. AADSTS54005: OAuth2 Authorization code was already redeemed, please retry with a new valid code or use an existing refresh token.
Trace ID: 37f11c2c-6450-4040-b297-48268c6d4b00
Correlation ID: afdeb0cb-c14a-4267-9a5d-2422a1f84d62
Timestamp: 2019-01-29 22:26:24Z",
"error_codes":[70002,54005],
"timestamp":"2019-01-29 22:26:24Z",
"trace_id":"37f11c2c-6450-4040-b297-48268c6d4b00",
"correlation_id":"afdeb0cb-c14a-4267-9a5d-2422a1f84d62"
}
So it looks like I need to pass a different code the second time I make a request to get access tokens, but where do I get this different code from?
I am using Twilio's latest SDK they released on CocoaPods as of today. I am trying to implement VOIP feature to my app with Twilio Programmable Voice. My backend is .net which also uses the latest release of Twilio Helper Library for C#.
My client code looks like:
fetchAccessToken { (accessToken: String) in
TwilioVoice.register(withAccessToken: accessToken, deviceToken: deviceToken) { (error) in
if let error = error {
NSLog("An error occurred while registering: \(error.localizedDescription)")
}
else {
NSLog("Successfully registered for VoIP push notifications.")
}
}
}
What I get in the console is as following:
voipTestWithTwilio[2431:517236] [ERROR TwilioVoice] Inside register:deviceToken:completion:, failed to register for Twilio push notifications. Error:Invalid access token signature
voipTestWithTwilio[2431:517236] An error occurred while registering: Invalid access token signature
This is the C# code that actually creates the token:
var grant = new VoiceGrant
{
OutgoingApplicationSid = outgoingApplicationSid
};
var grants = new HashSet<IGrant> { { grant } };
var token = new Token(
accountSid: accountSid,
signingKeySid: apiKey,
secret: apiSecret,
identity: identity,
grants: grants
);
return token.ToJwt();
I have been looking for the issue on the internet, nothing helped so far. I have tried contacting them but have not got any response back. I also tried creating new api keys and even a new project for a couple times on Twilio. Can anybody say something about the issue?
UPDATE
I added push notification sid to VoiceGrant and now I’m getting 403 Forbidden.
On Twilio error codes page it is explained as: “The expiration time provided in the Access Token exceeds the maximum duration allowed.” which is definitely not my case. However, I tried passing expiration parameter in Token constructor with various values which didn’t change the result.
The problem is still persisting.
I solved the issue. It was because my server returned the token with quotation mark.
I remember print(token)'ing on client (iOS) to see whether there is encoding issue or something and all I see was a proper token between quotation marks. Since token is a string value, I didn't pay attention to quotation part of it. That's where I was wrong.
I'm using the Google Identity Platform's OAuth 2.0 flow to authorize a javascript/HTML teacher observation form to write to a Google Sheets document. Everything is working well most of the time; however, last night one of our principals hit the following error:
"Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."
I determined that he had launched the observation tool in the afternoon, and now maybe five hours later was trying to click the submit button. My hunch was that the token had expired, but from Google's documentation it seems like the JS auth library is meant to handle refreshing the access token as necessary - I believe it's not actually possible to get a refresh token to do anything manually.
I'm using what is essentially the sample auth code, and the app responds to being signed out appropriately. That is, if I sign out in another tab, the submit button is disabled and the sign-in button appears again. Assuming token expiration is the issue here, any ideas on the correct way to identify if the token has expired and how to request a new one, ideally without user interaction? Or if it's not an expiration issue, what else could it be? This user has successfully submitted data in earlier observations; it was just this one time when he waited ~5 hours (potentially losing internet connectivity / sleeping his laptop) during that time.
Here's the auth code:
var clientId = ""; //id removed
var discoveryDocs = ["https://sheets.googleapis.com/$discovery/rest?version=v4"];
var scopes = "https://www.googleapis.com/auth/spreadsheets";
var authorizeButton = document.getElementById('authorize-button');
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
discoveryDocs: discoveryDocs,
clientId: clientId,
scope: scopes
}).then(function () {
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
});
}
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
document.getElementById('submit').disabled = false;
findRow(); //find the empty row once we're logged in
} else {
authorizeButton.style.display = 'block';
document.getElementById('submit').disabled = true;
}
}
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
Thank you!
Similar issues that i had resulted in issues from that Authorized Javascript origins.
"In the Authorized JavaScript origins field, enter the origin for your app. You can enter multiple origins to allow for your app to run on different protocols, domains, or subdomains. You cannot use wildcards. In the example below, the second URL could be a production URL." taken from https://developers.google.com/identity/sign-in/web/devconsole-project.If prompt to view task came from an email, the email origin must be verified -or- the device is used for multiple accounts, the token will not stay. If the api is being improperly used, it will allow functionality for a short period of time , then fail.
This may be useful, in the authflow, you do not have scope or id in options
/** * Initiate auth flow in response to user clicking authorize button. * *
#param {Event} event Button click event. */ function
handleAuthClick(event) {
gapi.auth.authorize( {client_id: '[#app:client_id]', scope:
["googleapis.com/auth/calendar"], immediate: false}, handleAuthResult);
return false; }
I believe How to refresh expired google sign-in logins? had the answer I needed. Since all of my API calls happen at once, I added a new Date() when the page loads, a second new Date() when the submission flow begins, and if they are more than 45min (2,700,700ms) apart, I use gapi.auth2.getAuthInstance().currentUser.get().reloadAuthResponse() to force an access token refresh, as documented at https://developers.google.com/identity/sign-in/web/reference#googleuserreloadauthresponse.
Hopefully Google will eventually update their documentation to reflect this now-necessary step when using the auth2 flow vs the older auth flow.
Time will tell if this actually solved the issue, but I'm hopeful!
I hope it helps you friend that error is because you have the wrong time, you go to date and time settings then press synchronize now.
I am getting Token Response Exception after 1-2 min continuously. After 2-3 min contacts coming and then after 2-3 min again token exception is coming.
Below is the Exception
com.google.api.client.auth.oauth2.TokenResponseException: 403 OK
<p class="large"><b>403.</b>
<ins>That's an error.</ins></p><p class="large">You are not authorised to perform this request. <ins>That's all we know.</ins>
</p>
I am retriving contacts of user , Below is my code,
ContactsService contactService = new ContactsService("appName");
contactService.setOAuth2Credentials(getCredentials());
Below is getCredentials() method.
public GoogleCredential getCredentials() {
GoogleCredential credential = null;
try{
Collection<String> SCOPES = new ArrayList<String>();
SCOPES.add("https://www.googleapis.com/auth/userinfo.profile");
SCOPES.add("https://www.google.com/m8/feeds");
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(SCOPES)
.setServiceAccountUser(adminEmailAddress)
.setServiceAccountPrivateKeyFromP12File(new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build().setExpiresInSeconds(min);
credential.refreshToken();
} catch(Exception e){
e.printStackTrace();
}
return credential;
}
can anyone tell me how to keep token valid for max time or how to deal with above problem.?
You need to understand how Oauth2 works I think you should read
Using OAuth 2.0 to Access Google APIs
Refresh the access token, if necessary.
Access tokens have limited lifetimes. If your application needs access
to a Google API beyond the lifetime of a single access token, it can
obtain a refresh token. A refresh token allows your application to
obtain new access tokens.
Note: Save refresh tokens in secure long-term storage and continue to
use them as long as they remain valid. Limits apply to the number of
refresh tokens that are issued per client-user combination, and per
user across all clients, and these limits are different. If your
application requests enough refresh tokens to go over one of the
limits, older refresh tokens stop working.
As stated in the doucmentation access tokens work for a limited amount of time. That being 1 hour you can't extend that. But you have the refreshToken you need in order to get a new AccessToken. RefreshTokens dont expire unless the user revokes your access. But in your case this wont happen becouse you are using a service account. So you can just rerun your code and get a new AccessToken
You have two options:
Check the time that is returned if your access token is about to expire then rerun the code and get a new one.
Wait until you get the error message then request a new access token.
The first option is best becouse google logs the number of errors you get from the API no reason to run something thats going to error on you. I normally request a new AccessToken 5 minutes before my old one is due to expire.