OAUTH access_token TTL - oauth-2.0

I've got an OAUTH2 Authentication Server which set a default TTL (3600s) for every new acccess_token.
But in my opinion the access_token TTL should be different for every Resource Server.
Like for a JavaScript Webinterface it should be 3600s, for an Android App it could be one month.
Who decides how long the access_token TTL should be?
Should the GET access_token request from the Client request a custom TTL?
Should the TTL for every Resource be defined in the Service Configuration (along with client_id, client_secret, App Description, ...) on the Authentication server?

The Authorization Server that issues the token is responsible for assigning an expiry time to it. There's no standardized authorization request parameter that the client can use to indicate the preferred TTL. The Authorization Server decides based on a policy that may be based on the client identifier and the associated/configured "permissions" or "trust", parameters available in the Authorization Request (e.g. scope) and other contextual data like HTTP request parameters, time of the day etc.

Related

Salesforce OAuth User Agent Flow: obtain refresh token with

I am developing a web application that allows any user to connect with its Salesforce account. I've implemented User-Agent Flow and I obtain correctly access_token and other info but I can't obtain refresh_token, even if I have the correct scopes (api, web, refresh_token, offline_access).
This is the request I use:
https://login.salesforce.com/services/oauth2/authorize?response_type=token&scope=refresh_token&client_id=[MY_CLIENT_ID]&redirect_uri=[MY_REDIRECT_URL]
And my redirect URL is:
http://[MYSITE].com/#/services/oauth2/success
(that corresponds to the host from where I make the call)
This call correctly gives me access_token but not refresh_token.
if I use "https" instead "http" as redirect uri I receive this error:
error=invalid_scope&error_description=the requested scope is not available
From the documentation, I read that:
The refresh token for the user-agent flow is only issued if you
requested scope=refresh_token and one of the following scenarios is
true:
....
The redirect URL host matches the request host and includes the servlet services/oauth2/success.
...
I think to be in this case, what am I doing wrong?
Thanks in advance
Try adding Perform requests at any time (refresh_token, offline_access) under Selected OAuth Scopes in your connected app

Quickbooks OAuth identify user of callback using state - Is this good practice and are there any security concerns?

I'm working on an application using OAuth2.0 for Quickbooks. I'm basing my code on the example provided by intuit. Here I have looked a bit on the "state" parameter of the oauthClient.authorizeUri.
oauthClient = new OAuthClient({
clientId: req.query.json.clientId,
clientSecret: req.query.json.clientSecret,
environment: req.query.json.environment,
redirectUri: req.query.json.redirectUri,
});
OAuthClient;
var authUri = oauthClient.authorizeUri({
scope: [OAuthClient.scopes.Accounting],
state: "userid:1234", //Encoded as a JWT
});
res.send(authUri);
});
I was thinking of encoding an internal user- and projectid in the state through a JWT only for this purpose. I need it for the callback to make sure that I'm connecting the right internal user with the QB token.
I have two questions here:
Is it "safe" to encode an internal userid in the "state" like that? Or is there a better way of doing what I want? I'm working with a distributed service (GCP CloudRun), so it might not be the same instance receiving the callback as the one that created the authUri.
I'm not an expert here, but a read of the spec seems to indicate this should not be a guessable value like user_id would be.
From the spec ( https://datatracker.ietf.org/doc/html/rfc6749#page-26 ):
state
RECOMMENDED. An opaque value used by the client to maintain
state between the request and callback. The authorization
server includes this value when redirecting the user-agent back
to the client. The parameter SHOULD be used for preventing
cross-site request forgery as described in Section 10.12.
and:
10.12. Cross-Site Request Forgery
Cross-site request forgery (CSRF) is an exploit in which an attacker
causes the user-agent of a victim end-user to follow a malicious URI
(e.g., provided to the user-agent as a misleading link, image, or
redirection) to a trusting server (usually established via the
presence of a valid session cookie).
A CSRF attack against the client's redirection URI allows an attacker
to inject its own authorization code or access token, which can
result in the client using an access token associated with the
attacker's protected resources rather than the victim's (e.g., save
the victim's bank account information to a protected resource
controlled by the attacker).
The client MUST implement CSRF protection for its redirection URI.
This is typically accomplished by requiring any request sent to the
redirection URI endpoint to include a value that binds the request to
the user-agent's authenticated state (e.g., a hash of the session
cookie used to authenticate the user-agent). The client SHOULD
utilize the "state" request parameter to deliver this value to the
authorization server when making an authorization request.
Once authorization has been obtained from the end-user, the
authorization server redirects the end-user's user-agent back to the
client with the required binding value contained in the "state"
parameter. The binding value enables the client to verify the
validity of the request by matching the binding value to the
user-agent's authenticated state. The binding value used for CSRF
protection MUST contain a non-guessable value (as described in
Section 10.10), and the user-agent's authenticated state (e.g.,
session cookie, HTML5 local storage) MUST be kept in a location
accessible only to the client and the user-agent (i.e., protected by
same-origin policy).
A CSRF attack against the authorization server's authorization
endpoint can result in an attacker obtaining end-user authorization
for a malicious client without involving or alerting the end-user.
The authorization server MUST implement CSRF protection for its
authorization endpoint and ensure that a malicious client cannot
obtain authorization without the awareness and explicit consent of
the resource owner.
Given that the spec recommends the state parameter be used for CSRF protection, and that the user_id is going to be easily guessable (i.e. the opposite of what you'd want for CSRF protection) it doesn't seem like a good idea to be putting the user_id into the state parameter.
Some other sources seem to confirm this:
https://auth0.com/docs/secure/attack-protection/state-parameters
https://medium.com/keycloak/the-importance-of-the-state-parameter-in-oauth-5419c94bef4c

Use an ID token or access token at userinfo endpoint?

I have a client API, that is a confidential client. When I authenticate with an open id provider, I am redirected to my callback with an authorization code, which is immediately exchanged to receive a refresh token, an access token, and an ID token.
Now, I create a session cookie that has a uuid for the authenticated user. When the user makes a request, do I...
Use my access token to call the providers userinfo endpoint to get the user info.
Read the validated ID token to get the users info.
When it comes to using the refresh token I see 2 options:
After reading a valid ID token or access token during a request, use the refresh token to get a new access or ID token to store at a new uuid, which is returned to the user with an updated cookie. While requiring the user to sign in more, this means the users session becomes invalid after inactivity on their part equaling the lifetime of the access or ID token. This is potentially more secure.
Use the ID token or access token until valid and then refresh to get a new one. If the refresh never expires, the user will never have to sign in again even if inactive for a long period of time ( unless cookie expiration is low ) Potentially less secure.
Thoughts?
A few notes first:
the lifetime of the application session is (typically) independent of the lifetime of the ID token; the latter is just an assertion about the user's identity, it doesn't represent a session
your first option doesn't work with a parallel requests e.g. when a user has opened multiple tabs to your application or the application uses Javascript calls
But foremost: a refresh token should not be used to get a new ID token, it should only refresh the access token; a user needs to be present to get a new ID token with the same semantics as the original one.
In short, you only use an authentication token to access userinfo_endpoint uri.
OpenID Connect allows the use of a "Discovery document," a JSON document found at a well-known location containing key-value pairs which provide details about the OpenID Connect provider's configuration, including the URIs of the authorization, token, revocation, userinfo, and public-keys endpoints.
You can research each applications unique discovery page uri from their docs for example here is
Google
You make a get request to the discovery document uri and from this document you find the userinfo_endpoint uri.
Example response from microsoft
GET https://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration
{
"authorization_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize",
"token_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
"token_endpoint_auth_methods_supported": [
"client_secret_post",
"private_key_jwt"
],
"jwks_uri": "https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys",
"userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo",
"subject_types_supported": [
"pairwise"
],
...
}
Google's discovery doc uri
GET https://accounts.google.com/.well-known/openid-configuration
Get an Authorization token. For example pull up Network -> Fetch/ XHR now look around and try to find a request header with the key 'authorization'. Copy 'Bearer {the id}' and put in the header of a get request like the picture shown below.
GET or POST /oidc/userinfo HTTP/1.1
Host: graph.microsoft.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6Il…
Microsoft Example Postman Request

OpenId Connect Implicit Flow with Resource Owner Password Credentials Grant

I'm currently working on an OpenId Server/Client for demonstration purposes and I struggle to understand the following specification.
http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest
1) The clientApp sends an request (ajax) to the serverApp in order to obtain a session id
2) The clientApp sends an authentication request (ajax) to the serverApp with
{
response_type : "id_token",
scope: "openid profile",
client_id: "clientApp",
redirect_uri : "clientAppAddress/redirecturi",
state: ???,
nonce: ???
}
There are no optional fields for grant_type, username and password (as in RFC6749: Access Token Request). How can I transmit the credentials?
Moreover I don't understand the concept behind "state" and "nonce". The specification says that nonce's value "needs to include per-session state and be unguessable to attackers. One method to achieve this for Web Server Clients is to store a cryptographically random value as an HttpOnly session cookie and use a cryptographic hash of the value as the nonce parameter.", whereas state is used to mitigate CSRF, XSRF "by cryptographically binding the value of this parameter with a browser cookie". Where is the difference between them and how do they increase security? I would use the hash-value of the sessionid (stored in http only cookie, and transmitted to the client in the first request) for both of them?
The actual method of authenticating the user, thus transporting credentials is not part of the OpenID Connect specification. The OpenID Connect specification merely tells you how to transport information about the authentication event and the user to a peer. The means of user authentication is independent of that.
The state parameter is there to correlate request and response and to share context between request and response. One of the things that you would typically associate with the state is the URL that the user is trying to access, so that after a successful authentication response you can redirect to that.
The nonce parameter is to prevent replay attacks since that value should be cached.
Together they are used to prevent Cross Site Request Forgery where an attacker got hold of the id_token and tries to use it against the RP to impersonate the user in the attacker's browser.
It would be better to use other values for state and nonce than directly derived from session_id since you may want to restart authentication from the same session and then nonce replay prevention would block you from reusing it (and distinguish between you and an attacker). Also state should be non-guessable, so not the same as previously used in the same session.

OAuth 2.0 for MVC - How does the RequestToken work?

I'm working with OAuth 2.0 for MVC, found here: http://community.codesmithtools.com/CodeSmith_Community/b/tdupont/archive/2011/03/18/oauth-2-0-for-mvc-two-legged-implementation.aspx
For anyone who's worked with this - I'm confused about the RequestToken. There is a controller implemented that lets you get a request token, which expires in 5 minutes, and you pass that token back in to get an AccessToken. But it never checks the request token for validity - it seems like you can pass in any access token you want to. What is the idea for the RequestToken here - are you supposed to create your own method of storing, referencing, and then deleting that token for those 5 minutes?
Thanks,
Andy
This is all about how OAuth works in conjunction with your application Id, application secret key and valid domains for your application. Here is the process in general
Your application sends a request to the OAuth provider using your application Id and secret along with a callback (return Url).
The OAuth provider gets the request, checks your application Id and secret and validates that the callback url is from a domain that you have specified for your application.
2a. If the callback url is not from a domain that you have specified, then the request is rejected with error.
2b If the callback url is from your domain, it returns a temporary request key to your server.
Given that you received a request key, you send that back to the OAuth provider to get the actual access token for the user.
Now, as to why the request key step is in place, this is to prevent and help protect 'bad people' from attempting to use your application id to falsely authenticate other users. By sending the request token to you (a callback URL that you have approved), the OAuth provider has confidence that the request actually came from your servers.
You most certainly could send any string back instead of the request token, but you would quickly get an error back from the OAuth provider as that request token does not correspond to any existing authentication request from any known application.
Lastly, I am not clear on what you mean by 'validating the request token'? You did not generate the token not probably do not have insight into the algorithm to generate the request token. Given that, I am not sure how you would validate this. If you are concerned about validating the first step, take a look at the Facebook OAuth process. In there, they recommend sending a request key as part of your return Url(as a query string parameter). That request key will come back to your application which you could then use as a validation that, indeed, this is a response to a request that you made. How you store and track that request key is up to you (session, database). In the PHP samples, they use a 'state' variable to track a unique/arbitrary string: Facebook OAuth Server Side Login Example (in PHP)

Resources