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:
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.