access token expiration/renewal - security

I have a personal website on which i want to display my latest facebook comment. Everything works fine, but I'm not sure how the access token expiration works. I have a two months access token, so does it mean that every two months I have to get a new access token and replace the one in my code. If so, it's really not convenient at all... especially since all this is to authorize MYSELF to get my OWN comments.
Is there a way to automatically renew the access token or to get a token that doesn't expire or any other way around this two months expiration thing?

According to Facebook documentation you can ping this URL, which will either return the same access token (if there is time left) or a new one (if there is not time left). This will return a string with a token and an expire time.
https://graph.facebook.com/oauth/access_token?client_id=APPID&client_secret=APPSECRET&grant_type=fb_exchange_token&fb_exchange_token=TOKEN

Related

Is it safe to store the oauth2 token in the UserProperties?

I am using the the oauth2 library to impersionate a service account with a user in order to access the google api in the context of that user similar to this example:
function getService() {
return OAuth2.createService('GoogleDrive:' + USER_EMAIL)
// Set the endpoint URL.
.setTokenUrl('https://oauth2.googleapis.com/token')
// Set the private key and issuer.
.setPrivateKey(PRIVATE_KEY)
.setIssuer(CLIENT_EMAIL)
// Set the name of the user to impersonate. This will only work for
// Google Apps for Work/EDU accounts whose admin has setup domain-wide
// delegation:
// https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
.setSubject(USER_EMAIL)
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getUserProperties())
// Set the scope. This must match one of the scopes configured during the
// setup of domain-wide delegation.
.setScope('https://www.googleapis.com/auth/drive');
}
As you can see, I am storing the bearer token in the Userproperties and I am wondering if this has some security implications.
Can the user access this token somewhere (afaik there is no UI in the Gsuite for that?)
What can the user actually do with this token (I think it will expire in 1 hour right?)
From the discussions on the comments, I would like to propose the following answer as the current answer.
Q1
Can the user access this token somewhere (afaik there is no UI in the Gsuite for that?)
A: When PropertiesService.getUserProperties() is used, the user can retrieve the saved values on only the same GAS project. And, it seems that the values cannot be retrieved with the Google APIs and UI. Ref
Q2
What can the user actually do with this token (I think it will expire in 1 hour right?)
A: At Google, the default value of expires_in of the access token is 3600 seconds. About this, you can check this using the following curl command.
curl "https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=###"
Q3
if the user somehow can retrieve this token somehow and use this for getting access to services he should not have access to.
A: For the standalone GAS project, when the users have no permission for writing the script, the users cannot directly see the access token (In this case, users cannot use the log.), while the script can use the user's access token.
Note:
Above situation is for July 10, 2020. Google Apps Script and Google APIs are growing now. So these specification might be changed in the future update. Please be careful this. When I could confirm the specification was changed, I would like to update this answer.

JWT With Role Based Access Control

Say I want to use JWT for authentication, and in the case of users who are using the API of my application directly I would like to issue a token that does not expire (but does contain an ID so that it can be revoked). Secondly, say I have a role based access system, where I would also like to encode the user's role into the token. However, how do I solve the problem that the user's role may change but that the token would still encode it? Obviously if someone's role changed to some thing with less privileges this would be a security issue? The issue isn't just restricted to this use case either, theoretically active tokens would have the same problem of role changes not taking immediate affect.
My initial solution is too not encode role/permission levels into the primary token, and instead use a secondary token that would only be added to request to my system upon passing through the application's boundary from the greater internet, but I'm also wondering how other people solve this problem?
If you need to invalidate tokens, you'll have to keep track of the tokens you issued and make sure you can "remove" them at some point in time.
My suggestion would be to use one token, and track somewhere a relation between USER and TOKEN_VALID_IF_ISSUED_AFTER.
At that point, when a user logs out, when their permissions change, when they change password... ...you can insert a record in this table with $USER_ID and NOW().
Next time a token goes through your API you validate that it was issued after the TOKEN_VALID_IF_ISSUED_AFTER through the iat claim -- if not, the user will have to get a brand new token.

Azure Active Directory graph api - How to regenerate expired page token

I am using Azure AD graph REST API to get all users on the Azure Active Directory. I am also using paging while getting those user.
At the end of each page, api returns token for the next page. Which is used to get next page of users.
It looks like this - "odata.nextLink": "directoryObjects/$/Microsoft.DirectoryServices.User?$skiptoken=X'226370740200010000003E3ACDE316230633836636636373430323861666235626436306537366132306139407361696C706F69AEFDE746465762E6F4F4F4F418F736F66742E636F6D29557365725F383461663866351238412782482433372D626439312D336239633930373536383464B900CCCC00001111000000'"
}
For some reason if there is delay in using this next page token, it expires. API throws error 'Bad Request The specified page token value has expired and can no longer be included in your request.'
So how to regenerate valid page token for next page without starting again from the beginning ?
What is the default validity for the page token ? I guess it is 1 hour. Is it possible to increase this time ?
Looking around on existing graph documentation, there is no mention of any explicit manner to extend this token.
Considering there does not seem to be a way to extend it, you should make your app code advance as much pages as it did (caching it somewhere), to continue from there.
You should also consider restarting from the beginning, as one hour can be long enough to have your user list potentially been modified.

Obtaining Instagram Access Token

We have a client who has a simple Instagram feature on the site to pull photos by a certain tag. They just noticed it isn't working. Getting an error - invalid access token. I guess since the 1st because of the updates. We didn't used to need an access token since we're not doing anything with users - just tags.
Now it looks like we need one and the documentation makes zero sense on how to obtain one. And it seems like they're not accepting most apps. The app is in sandbox mode too. So I'm assuming it's because it got switched to that? Got no notification of this happening.
The first step in documentation to get an access token is "Direct the user to our authorization url." What does that even mean? There's not a link provided or anything. It also says "Company Name, Contact Email and Privacy Policy URL are required to start a submission." Our app doesn't have a privacy policy... it's just a simple tag feed. I don't understand why everything is so complex to have a simple tag feed.
Is there a wait time to get the app approved..if it gets approved... Do I have to have it approved before getting an access token? This isn't outlined anywhere.
You got it right. As of June 2016 any Instagram API calls require an access token.
Getting an access token is described in the documentation. App approval is not required.
There are two ways to get one: server-side or client-side. The second option (called implicit authentication) can only be used when implicit OAuth is enabled in the client settings (Manage Clients > Edit Client > Security > Disable implicit OAuth). It is disabled by default.
In either case you need to redirect the user to the authorization URL to obtain an access token.
The URL for explicit mode (server side) is:
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code
The URL for implicit mode (client side) is:
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token
After this you will be redirected to the REDIRECT-URI, which will be passed an argument. For explicit mode this will be a query string with a code, while for implicit mode you will get the access token directly as a hash:
http://your-redirect-uri?code=CODE
http://your-redirect-uri#access_token=ACCESS-TOKEN
For implicit mode you can then get the access token from the window.location.hash in Javascript.
For explicit mode, however, you need to further process the code to obtain the access token. You can read how this can be done in the API Documentation. I'm not going to take this any further here.
The problem is that every user who wants to see your feed needs to login to Instagram (and have an account) in order to view it. In your case this might not be desired. However, there are a few options to get around this (rather annoying) problem:
You can reuse your own (already obtained) access token(s) to display the Instagram feed for every user. You will need to be aware of rate limits for each token. For sandboxed apps this is 500 API calls / hour, while live mode allows 5000 API calls / hour. [source] You could store tokens in a table and use them in a round-robin manner, to allow more API calls. This involves manually obtaining a bunch of tokens which your application can use (the more the better). This might not be the ideal solution considering Instagram doesn't warrant access tokens to have an unlimited lifetime.
You can retreive JSON data without authentication by appending /media/ to a user page URL, as described in this post. No tokens or client IDs are required for this to work. However, this only works for users, not for tags. Besides, Instagram doesn't document this feature so it is not garanteed to work in the future.
You can use an aggregator like Juicer or Dialogfeed instead which will handle access tokens for you. This is usually not free of charge.
I'm also in the process of making an Instagram feed for my website, and this is what I concluded from my research. Please bare with any errors I made.
Edit: Here are some more limitations for sandbox apps.
In sandbox mode you can only access data from sandbox users (thus users who received a sandbox invite). This means that:
Media retreived by user, e.g. /users/{user-id}/media/recent, will return an empty response if the user is not any of the sandbox users.
Media retreived by tag, e.g. /tags/{tag-name}/media/recent, will only contain tagged media belonging to sandbox users.
Thus, for a tag feed to work, it needs to be live (reviewed and approved). If you don't want to do this, the only alternative is to use an aggregator as I mentioned above.

Azure Oauth - how to change token expiration time?

We are using Oauth2 with Azure. And by default server returns token with an hour interval for expiration. Is there any way change expiration interval?
It is now possible to configure the token lifetime. You can read more here: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-configurable-token-lifetimes.
Remark: This feature is in preview and will not go to production in this way. The following header is also placed on the documentation link I mentioned above.
After hearing from customers during the preview, we're planning to replace this functionality with a new feature in Azure Active Directory Conditional Access. Once the new feature is complete, this functionality will eventually be deprecated after a notification period. If you use the Configurable Token Lifetime policy, be prepared to switch to the new Conditional Access feature once it's available.
Original answer:
Currently there is no way to change the expiration interval. These are the current expiration times.
Access tokens last 1 hour
Refresh tokens last for 14 days, but
If you use a refresh token within those 14 days, you will receive a new one with a new validity window shifted forward of another 14 days. You can repeat this trick for up to 90 days of total validity, then you’ll have to reauthenticate
Refresh tokens can be invalidated at ANY time, for reasons independent from your app (e.g. user changes password). Hence you should NOT take a dependency on the above in your code – your logic should always assume that the refresh token can fail at any time
Refresh tokens issues for guest MSA accounts last only 12 hours
Source: http://www.cloudidentity.com/blog/2015/03/20/azure-ad-token-lifetime/ and also my own experiences.
You have to use power shell to perform 2 steps as below:
Create new policy. This policy sets timeout 2 hours
New-AzureADPolicy -Definition #('{"TokenLifetimePolicy":{"Version":1,"AccessTokenLifetime":"02:00:00","MaxAgeSessionSingleFactor":"02:00:00"}}') -DisplayName "MyWebPolicyScenario" -IsOrganizationDefault $false -Type "TokenLifetimePolicy"
Apply this policy to your website
Add-AzureADServicePrincipalPolicy -Id <ObjectId of the ServicePrincipal> -RefObjectId <ObjectId of the Policy>
Note:
In order to get ObjectId of the ServicePrincipal, run this command: Get-AzureADServicePrincipal
To get ObjectId of the Policy, run this command: Get-AzureADPolicy
For more detail you can refer to this document: https://learn.microsoft.com/en-us/azure/active-directory/active-directory-configurable-token-lifetimes
Assuming you're talking about Azure AD, AFAIK it is not possible to do so.
However, in the response along with token you get back a refresh token as well that can be used to get a new token. What you can do is cache the refresh token and expiry time and before making a request you can check if the token has expired (or about to expire). In that case you make use of this refresh token to get a new token and then make your request.

Resources