O365 MS Graph Unified API token lifetime - odata

I have two questions about token usage and their expiry:
1) about user's secret code for application
I need secret code to authenticate. When creating secret code in application it can be defined with expiration one or two years. My goal is application which user installs, sets up, and it can be 'forgotten'. But this expiration could mean that application will start failing after one year, is that correct? User will start to get token errors and he will have to re-setup the application again (generate new secret key and authenticate with it). Can I find out expiration from secret key, so I could set up a notification for user BEFORE it gets expired? I'd like to do that to avoid application stop working just suddenly.
2) client authentication is done in two steps:
one: app client id + client secret key + source + user authentication = code
two: app client id + client secret key + code = token + refresh token
I found that if I do step one and I want to perform step two later then 'code' from step one may be expired. I thought that 'code' does not expire, but I can't find any documentation about that. Is that correct, that step two should be done right after step one?

1) If that is a web service, you could use OAuth 2.0 Client Credentials Grant Flow . In consideration of security , I would suggest you could maintain/update the secret key periodically , the duration of the secret key could be one year or two years . If the secret key is compromised, a new one must be generated and all authorized apps will have to be updated with the new client secret.
2) You could click here for details about how to use OAuth 2.0 to authenticate. In Service-to-Service access token response, you will get the expires_in(How long the access token is valid) and expires_on(The time when the access token expires) information . You should write your code to anticipate the possibility that a granted token might no longer work and request a new one .

Related

Google oauth2Client.getToken is not returning id_token for other users

I'm implementing Google's 'code model' of Oauth2 and having trouble getting users' email - I wonder if this is a scopes problem or my misunderstanding about how to set up the code model. This sequence of events is already working:
Client loads https://accounts.google.com/gsi/client
Client starts call to google.accounts.oauth2.initCodeClient
Client gets code
Client passes code to one of my server endpoints
Server has an oauth2Client set up using the config with client_id, client_secret, and redirect URL = 'postmessage'
Server exchanges the code from the client for tokens
Server does oauth2Client.setCredentials(tokens) - this contains an access_token, which is enough for the client to make API calls to, e.g., retrieve the user's Google Calendar
Server is able to do oauth2Client.getTokenInfo(tokens.access_token);
There are various places along the way that involve scopes; I am probably getting something confused here. The client's initial call (step 2 above) uses
scope: 'https://www.googleapis.com/auth/calendar',
My code path on the server does define scopes anywhere.
In GCP, my project is set up with scopes
calendar.calendarlist.readonly, calendar.readonly and calendar.events.readonly
openid
/auth/userinfo.email
Here's the problem I'm encountering: when I go through this flow as a user and oauth with the account that owns the GCP project (this is a Google Workspace email, in case that matters), the tokens object that the server receives (step 6 above) has access_token, refresh_token and id_token - the id_token can be decoded to yield the user's email, and the user's email is also in the response to oauth2Client.getTokenInfo(token.access_token).
However, when I go through the flow with my other (personal) Gmail account, the tokens object that the server receives is missing the id_token but has the access and refresh tokens. Question 1: why are the responses different?
Question 2: How can I get the email of the user on the server in the personal Gmail account case? I've tried having the server make a call to https://www.googleapis.com/oauth2/v2/userinfo?fields=id,email,name,picture with the access_token, but this fails. I am not sure if I'm supposed to declare scopes for oauth2Client somehow, or tap a Google API using a different method on the server.
I think I've had a breakthrough: in step 2 in my original post, when I did "Client starts call to google.accounts.oauth2.initCodeClient", I had set the scope of initCodeClient to just the calendar scope. When I changed it instead to scope: 'https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/userinfo.email openid', (scope takes a space-delimited list in this case), it allowed my server call to get the id_token for this user and oauth2Client.getTokenInfo to get a response with the user's email in it.
When I updated the scopes like that, the popup asking for authorization also updated to request all the scopes I wanted - previously, it was only asking for the Calendar scope, so it makes sense Google didn't want to return the email.
What I still don't understand is why my previous setup was working for the account that owns the GCP project. In other words, when I was first building it out with that owner account, the client was only noting the Calendar scope while the server was asking for all three scopes (ie there was a mismatch), and the server was still able to get an id_token and the user's email in getTokenInfo. Maybe the owner account has some special privilege?

Using nodemailer & Google OAuth to send email, working for 7 days, but get invalid grant

I've been working to setup Oauth communication for an auto-emailing node.js web app using nodemailer. (I don't wish to use gmail's Less Secure Apps setting).
I've taken steps to get the client id, secret, and refresh token from the oauth playground, and have set up the web app to use a stored refresh token to request new access tokens when it first loads.
It is able to send emails (for about 7 days), then I get error invalid status code 400 on client side, and/or invalid grant on server side.
Going back to google playground and getting another refresh token, then updating it in environment variables, solves this for another week. But I'd like to solve this indefinitely.
I read somewhere "A Google Cloud Platform project with an OAuth consent screen configured for an external user type and a publishing status of 'Testing' is issued a refresh token expiring in 7 days"... so last week I switched the app to "In Production" (at console.cloud.google.com) and tried having it verified with google. This week, the same issue has recurred suggesting that wasn't the right fix, or that it wasn't yet verified with google.
I don't know if this was done correctly, nor do I know if this is the true solution to this expiring/revoked refresh token, or invalid grant.
I've also come across these explanations:
The user has revoked your app's access.
The refresh token has not been used for six months.
The user changed passwords and the refresh token contains Gmail scopes.
The user account has exceeded a maximum number of granted (live) refresh tokens.
The client has reached a limit of 50 refresh tokens per account if it's not a service account.
(I didn't make ANY changes during the week, so...not sure why these would have changed)
Is the issue the refresh token?
Or the status of the application?
Would it be dns/cname/cloudflare server issues?
For those who have the same issue in the future:
It turned out that google verification wasn't necessary.
It seems like the refresh token expiring after a week or 7 days was due to the placement of the oauth2Client.setCredentials() function call and accessToken variable.
Calling setCredentials() and obtaining the access token INSIDE the SendEmail() function (at runtime, just before sending email, rather than at application start/spinup time) seemed like it enabled the code to more dynamically generate the tokens it needed. After 12 days, it still seems like its working so I'd call this a success.
My guess at why it wasn't working before was because setting credentials outside of a function meant that code only ran once on server/application startup. It would then store the obtained access token in a const.
The access token would eventually expire, and even if called again/later inside of a function to obtain a new access token, it would be unable to change the value of a const property/variable, and so the call would inevitably fail after a week when it failed to renew.
Hope this helps anyone else having a similar issue.
My apologies for the run-on sentences.
There are a lot of causes for invalid grant it sounds to me like your refresh token is expiring.
If your project on google developer console is still in testing, has not been moved to published and has not gone though the google application verification process then refresh tokens have a max two week life span after which they will expire which may explain your invalid grant. The thing is there is no official word from google that this is happening its just what a lot of developers are seeing these days.
Another one is with gmail scopes if the user changes their password this will also cause the refresh token to expire.

Disable one time use on refresh tokens in Datapower/API Connect [OAuth2]?

We have an OAuth/OIDC service developed in API Connect/Datapower.
When a user requests a new refresh_token - if any unexpected error occurs in the flow, the new refresh_token is not issued, and their existing refresh_token is revoked. This forces the user to go through a new consent flow. This can be problematic if large numbers of customers are affected due to some unexpected error. We would like the old refresh_token to still be valid in this scenario.
We raised this with our IBM support contact - and he said this works as intended (i.e. - it should revoke the old refresh_token as the first action - it is single use, regardless of outcome).
He did suggest that it is possible to configure the refresh_token to be used multiple times until it is revoked/expired.
I am not sure how to do this - or what versions it is supported in. He said '(in 2018.4.1.x)? For v5 gw, use extension to enable it, You will need the latest DP firmware release for the above'. It's been hard to get any clarity on this. The IBM developer forums even directed me to Stack Overflow...
Does anyone have any more information/experience with enabling a refresh_token to be used multiple times? Or what versions this is supported in (or links to any documentation about this)? I'm struggling to find anything concrete on this.
Thanks
I suppose he's talking about the count configuration. it is located just below Enable refresh tokens.
Section 'OAuth 2' -> Tokens -> Enable refresh tokens -> count
Hope this could be helpfull
For IBM API Connect version 2018.4.1, you can specify whether the refresh token for OAuth provider is One time use only or not.
See OAuth native provider>Tokens screen.
After an access token expires, if the option is enabled in the OAuth provider API, the application can use refresh tokens. Each refresh token is valid for approximately 31 days after it is issued and can be used only once to request a new access token. Along with the new access token, a new refresh token is also returned.

How is access token refreshed / acquired when using API Client Library for .NET?

I have one quick question related to "acquiring a new access token upon expiration". I have read some tutorials where people write code to manually request a new access token.
In my case I wrote an ASP.NET MVC app to access Google APIs, such as Gmail API, and I am using API Client Library for .NET for that.
After OAuth 2.0 authorization I get back the result object of type AuthorizationCodeWebApp.AuthResult.
Where result.Credential.Token contains AccessToken and RefreshToken properties.
I save the refresh token in my web.config the very first time when it comes back (after the consent screen). All next requests dont have a refresh token, only an access token that expires after 1 hour.
So, my question is - before I make a call to instantiate a Gmail Service, I assign previously saved refresh token:
result.Credential.Token.RefreshToken = WebConfigurationManager.AppSettings["RefreshToken"];
var service = new GmailService(
new BaseClientService.Initializer { HttpClientInitializer = credential });
When result.Credential.Token.AccessToken expires, does Gmail API (or any other API Client Library for .NET) acquires a new access token automatically if result.Credential.Token.RefreshToken was assigned a valid refresh token value previously saved, like in my code sample?
Thank you!
UPDATE - More clarification to my question With the same refresh token, how many times I can aquire a new access token when making calls to Google API?
I will explain: access token expires in 1 hour, right.
If I keep making calls with, lets say, 10 minutes intervals to Gmail API (for example), after 6 calls (1 hour limit), Gmail API will use my refresh token to acquire a new access token. After 6 more calls (1 more hour) the whole thing repeats itself. Question - is there a limit to it? Remember, I am not changing my refresh token. Same refresh token is being used to acquire a new access token. And for how long this repetitive calls may continue without any error?
UPDATE AFTER THE TEST
I let my application run on my local machine in Visual Studio DEBUG mode trying to catch any exception, NO Human interaction.
The application kept receiving AJAX calls to Gmail Action with 2 minutes interval, everything was working fine, I went to the gym, came back 2 hours later - oops, Visual Studio debug is open on this Token has been revoked exception, here we go, so it's clear the token was revoked by the Google API service, as you can see from the Debug window. The only question remains - why, since there are no specific details are provided, there is no Inner Exception just that general error message and no reason, but the source is clear - Google API, we can even see it came back from
Google.Apis.Requests.ClientServiceRequest`1.Execute() в
C:\Users\mdril\Documents\GitHub\google-api-dotnet-client\Src\GoogleApis\Apis\Requests\ClientServiceRequest.cs:row
96
I am guessing the service shuts down (revokes a token) after N number of calls, maybe within certain interval. If some one knows the limitations of Google API in terms of number of calls or time intervals between calls, please let me know.
It seems that Matthew Riley, the custodian of Google API on github, coded some logic to revoke a token based on some criteria: https://github.com/google/google-api-dotnet-client
Long response to comment :
One question though: can this be done indefinitely long, unlimited number of times, or I will get an error at some point?
Refresh tokens can be come invalid for the following reasons:
user can revoke it in there google account.
if a refresh token isn't used for 6 months to get a new access token it will expire automatically.
If a user authenticates your application you get a refresh token if they do it again you get a different refresh token. Both will work. you can do this up to 26 times. on the 27 th time the user Authenticates your application the first one you got will expire. You can only have 26 live refresh tokens. (DONT ASK how I know this! "#¤%&)
So assuming you don't reauthentcate your application to many times, use the refresh token at least once every six months. You can use it as many times as you want.
Update for comment:
I think you are still confused. Access tokens expire after 1 hour. Refresh tokens only expire for the above reasons you can use them as many times as you like. To get a new access token.
However you can only have 25 working refresh tokens.
Lets say I have a windows service application that backs up files to a users Google drive account. A user installs it on a server and authenticates it and gets a refresh token. Every night the windows service runs and backs up the files to google drive, it uses the refresh token to get a new access token.
Lets say this user really likes my auto super imba backup service. He installs it on another server. He gets another refresh token and the application goes about its business uploading files at night
Lets say my super user really has a server farm he installs my application on 25 servers. Those applications will be able to get new access tokens forever.
However if this crazy user installs it the 26 th time on a different server getting a new refresh token for this server. The first server they installed it on will stop working because google only allows you to have 25 outstanding refresh tokens for an application.
This is user application based so you can have any number of users each with a max of 25 refresh tokens

How to renew access token secret for Intuit QuickBooks integration with .net application?

I am using code in following link to Renew access token for Intuit QuickBooks integration.
https://gist.github.com/IntuitDeveloperRelations/7259345
but, I am unable to test this code as intuit renew its access token only after 150 days from token creation date and I've created token only few days back. So I don't know the output. Right now, it is generating xml response with error message.
Now this method is returning me a single string which seems to be the Access Token. Do I also need to renew Access Token Secret ? If yes, then how to generate it ? Or the output contains secret as well ?
Actually, Can you give me the output for this method?
A successful response looks like this:
<ReconnectResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://platform.intuit.com/api/v1">
<ErrorMessage/>
<ErrorCode>0</ErrorCode>
<ServerTime>2012-01-04T19:21:21.0782072Z</ServerTime>
<OAuthToken>qye2eIdQ5H5yMyrlJflUWh712xfFXjyNnW1MfbC0rz04TfCP</OAuthToken>
<OAuthTokenSecret>cyDeUNQTkFzoR0KkDn7viN6uLQxWTobeEUKW7I79</OAuthTokenSecret>
</ReconnectResponse>
Refer to Intuit's documentation.
Notice that you will get back both a new token and a new token secret which you should store.
Remember that you can use Intuit's OAuth Playground to generate shorter lived tokens to test with.
You can test Reconnect API in the following way-
1. Navigate to IPP Playground- Go to Manage My Apps->Click on your app
Fill in consumer key and consumer secret in links below.
Prod: https://appcenter.intuit.com/Playground/OAuth/IA/?ck=prodConsumerKey&cs=prodConsumerSecret
Alternatively, you can navigate to the Manage page for your app on stage or prod and click ‘Test connect to app (OAuth)’.
Enter the duration you would like for the issued OAuth tokens (e.g., 3600 for successful Reconnect) in the ‘Access Token Duration’ field.
Click on the Connect to QuickBooks button, go through OAuth flow to authorize a connection to a realm.
Under the resulting Post-Connection Interactions heading, click ‘Reconnect API Test’. Screen shot attached.
A new page will launch where your OAuth tokens are displayed. Copy these values to your application to test Reconnect.
See if this reconnection code sample helps:
http://developer.qbapi.com/Reconnect-to-Quickbooks-Online-.aspx

Resources