In OAuth 1.0, 2-legged is pretty easily: Simply send the request as usual and omit the access_token header.
Things seems to have changed in OAuth 2.0 (drastically, as I found out today :)). In OAuth 2.0, the request no longer has headers such as the nonce, consumer key, timestamp etc. This is just replaced by:
Authorization: OAuth ya29.4fgasdfafasdfdsaf3waffghfhfgh
I understand how 3 legged authorizations work in OAuth 2.0 and the application flows. But how does 2-legged work in 2.0? Is it possible to design an API that can support both 2-legged and 3-legged OAuth 2.0?
I have been searching for information regarding this, but I have been finding a lot of stuff on 2-legged for 1.0 and almost nothing for 2.0.
After lots of research, I discovered that client_credentials grant type is for this scenario. Once you punch this term into google, you can find loads of very helpful resources.
This is the normal flow for 3-legged OAuth 2.0 (we want the user to sign in):
Assume we have the following endpoints in our app for authentication:
/oauth/auth
/oauth/token
Normally (for authorization code grant), we direct the user to /oauth/auth?state=blah&client_id=myid&redirecturl=mysite.com/blah
Then upon authentication, the user is redirected to mysite.com/blah?code=somecode
We then get somecode and exchange it for a token using /oauth/token?code=somecode&client_id=myid&client_secret=mysecret
We can then use the token to make calls.
This is the application flow for client_credentials to implement 2-legged OAuth 2.0, which is markedly simplier:
In this approach, we do not need to perform any authentication.
We simply POST to /oauth/token with the following form data:
grant_type=client_credentials&scope=view_friends
Note that scope is optional. The endpoint then directly returns an access token for us to use (no refresh token is provided). Since no refresh token is provided, when the token expires, you will need to reauthenticate and ask for a new one.
This leads to the following caveats:
Use this only for (very very) trusted applications such as internal applications.
You need to devise your own way to authenticate. For instance, the RFC's example uses basic auth.
Another solution is to use JWT (JSON web tokens) like the google OAuth API. It is a very complicated process, but there exists numerous libraries for generating your JWT. You then post the following form data (url encoded of course):
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=generated_jwt
This is posted to /oauth/token to get your token.
As for the question of whether you can create an API that supports 2-legged and 3-legged OAuth 2.0, Yes, it is possible.
Then /auth endpoint is only used when users need to authenticate against the service.
In the /token endpoint, simply check the value of grant_type in the GET parameters for urn:ietf:params:oauth:grant-type:jwt-bearer if using JWT or client_credentials for client_credentials.
Note that when generating the client_id and client_secret to give to the user, if you are supporting multiple grant_types, ensure that you have a database column to store what type of grant type the id and secret was generated for. If required to have multiple grant types per user, generate a different set of credentials for each grant type.
You can also check out Google's implementation of 2-legged OAuth2 (I believe this documentation has been published only recently).
The Google Drive SDK delegation docs should also help understanding Google's 2-legged OAuth2 implementation.
Related
I know that the access token obtained from OAuth2.0 can be used to access protected resources.
OpenID Connect issues ID token and access token after authentication. And the spec says that the access token can be used to access userinfo endpoint to get additional user information.
One thing I'm not able to understand is, is there any difference between the access token obtained in #1 vs #2. If there is no difference then do we need OAuth2.0, if we implement OIDC.
You tend to just implement both OIDC and OAuth 2.0 together as a combined flow, by plugging in an Open Id Connect security library.
Eg For a mobile app it is common to plug in AppAuth Libraries, which would give you this behaviour:
An OAuth 2.0 authorization redirect using response_type=code
The Open Id Connect part is initiated by including scope=openid
You then get an authorization code (OAuth 2.0)
You then swap the authorization code for tokens
You get an access token (the OAuth 2.0 part)
You also get an id token (the OIDC part)
In practical terms OIDC introduces some standardisation that makes developing UI flows and dealing with access tokens in APIs easier, eg:
Metadata endpoint, to tell us where all the other endpoints live
JWKS endpoint, from which we can get the access token's public key
Typically in my own code I do not use the id token much at all. However, it is best practice to receive one, so that libraries such as AppAuth can make extra verification checks against received tokens.
If it helps, my Message Workflow Blog Post summarises some messages and use of endpoints.
This access tokens have different audiences ("aud" claim): the OAuth 2.0 access token is intended for resource server (i.e. API), and OIDC access token is intended for identity server itself.
As for me, they cannot be used interchangebly, but some examples (e.g. IdentityServer4) do that without checking the "aud" claim.
PS. The single access token can be used for both purposes if both audiences are included:
Each principal intended to process the JWT MUST identify itself with a
value in the audience claim.<...> In the general case, the "aud" value
is an array of case-sensitive strings, each containing a StringOrURI
value.
JWT doc
I am confused about the use of OAuth 2.0 as an Authorization method and OpenID Connect as an Authentication method.
Based on my knowledge OAuth 2.0 is only an Authorization method. In other words, this is the process to request an ACCESS_TOKEN and RECEIVE this ACCESS_TOKEN, like depicted in the image below in yellow ellipse: (simplified)
Before an OAuth 2.0 Client retrieves an ACCESS_TOKEN from an Authorization Server this Server should verify if the User allows it and this is an Authentication Process that OAuth 2.0 does not care about.
When OpenID Connect is included in the mix it allows for an Authentication Method as well, but in my knowledge OpenID Connect just adds a "Claim" in the JWT Token that holds information about user that is using the service, like: email, name and others.
My questions are:
Why not ignore OpenID Connect and just add more "claims" in OAuth
2.0 to get information about users?
Is my description of the flows correct?
OpenID Connect does not merely "add a claim in JWT Token" but:
it introduces a completely new token (id_token) with radically different
semantics than the OAuth 2.0 access_token and a standardized format that is understood by the Client as opposed to the access_token which is opaque to the Client
it "twists" the role of the Client, now becoming the "audience" (or: intended recipient) of a token (i.e. the id_token) whilst the audience of the access_token is still a remote entity (aka. Resource Server) and the Client is only the "presenter" of the latter
The 2nd item is the primary source of confusion between OAuth 2.0 and OpenID Connect.
I don't know if your method will work or not but you're totally free to roll your own authentication. After all, that's what Facebook, GitHub and many others did by customizing oauth2. There ended up being so many oauth2 "authentication" methods that it was never plug and play if you wanted to change your provider. I believe that's why OpenID connect was introduced--a common way of connecting and reasoning about authentication while building on the established oauth2 pattern for authorization. Use OpenID connect or don't...but if you don't you'll be reinventing the wheel.
#sdoxee answers explains thing correctly. But I am adding bit more information for OP's understanding.
These days many identity providers (eg:- Azure AD) issue JWT based access tokens. These JWT access tokens do contain claims about end user as well as JWT related validation details (eg:- Token expiration). Here is the link for Azure AD OAuth 2 success response which highlights access token to be a JWT. Also, see JWT claims to see how they explain the claims. Samples are given below,
family_name : User’s last name or surname. The application can display this value.
given_name : User’s first name. The application can display this value.
One could think of building authentication on claims present in access token, but this is not sticking with protocol. And mostly claims and user information will be implementer specific. Also, by protocol definition, these two tokens (id and access) have two different audiences.
ID token is for client, for validation and for authentication.
Access token is for OAuth 2 protected endpoint.
Again, as #sdoxee highlight, use the correct protocol at correct place. Having claims in access token does not necessarily mean you should use them for authentication.
I've been trying to learn some server side frameworks these days. I am not an expert of oauth2, but I had use an api with a team. They gave me an access using Resource owner credentials grant, with a grant_type as password, client_id and client_secret. I can log in on multiple browsers at the same time. As I have tried sails js oauth 2 and laravel passport oauth2. I got confused. Both of them using grant_type password revoke my old access_token. Using laravel passport and sails js oauth2 with grant_type password. I can log in only on one device or browser at a time. I'm confused which one is the right thing to do.
Is this how oauth2 really works? you can only log in and use one access token?
If this is the standard way, revoking the old access token. What type of grant type should I use. so my multiple devices can log in at the same time?
The behavior --- whether issuing a new access token invalidates existing access tokens or not --- depends on OAuth 2.0 server implementations. The OAuth 2.0 specification (RFC 6749) does not impose any restrictions on the behavior.
In fact, a certain OAuth 2.0 server implementation provides a feature to enable server administrators to configure the behavior. The following is a screenshot of the description about the configuration item ("Single Access Token Per Subject").
So, what matters is not grant_type but the implementation policy of the OAuth 2.0 server you are using.
I am working on a web app which will need to implement the three-legged OAuth 2.0 flow. The Smartsheet API docs http://smartsheet.com/developers/api-documentation say that the API supports standard OAuth 2.0 flow. On closer inspection, however, I see that access and refresh token management operations require that instead of sending over the client secret (which appears to be the standard behavior in other APIs), I have to send over a hash, quoting "SHA-256 hash of your client secret concatenated with a pipe and the authorization code. The client_secret is never sent with the request."
Given that this is different from the standard OAuth 2.0 flow, does Smartsheet API support the standard behavior?
Passing the secret in the clear - on the URL - is not supporterd. The flow described in the documentation is an OAuth2 flow, though it is admittedly not the common flow that is most generally used among SaaS vendors. The OAuth2 spec allows for extensions to the token endpoint to accommodate the security requirements of the authorization server, and the SHA256 hash is one such extension.
Is it possible to get a Twitter access token with OAuth 2.0? I came along this thread but I don't understand it. Do they support OAuth 2.0 or are they still using OAuth 1.0A?
Quoting from this page:
Twitter offers applications the ability to issue authenticated
requests on behalf of the application itself (as opposed to on behalf
of a specific user). Twitter's implementation is based on the Client
Credentials Grant flow of the OAuth 2 specification. Note that OAuth
1.0a is still required to issue requests on behalf of users.
Therefore, no they do not fully support OAuth 2.