OAuth 2.0 and OpenID Connect API
OAuth 2.0
According to RFC6749, OAuth 2.0 is "an authorization framework that enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf."
The OAuth 2.0 RFC defines multiple ways an application can get an access token, and it refers to it as grant_types
. The protocol defines four grant types, which the OneWelcome Identity Platform implements, such as:
- Authorization code
- Client credentials
- Implicit
- Resource owner password credentials
These grants serve different purposes, meaning different grants are suited for different use cases, such as web applications, server-to-server applications, or devices that are not able to launch a web browser.
Endpoints
The OneWelcome Identity Platform implements the endpoints defined by the OAuth 2.0 and OpenID Connect RFC. The full API definition can be found in the OAuth 2.0 & OpenID Connect API specifications.
Authorization code grant
The authorization code (AC) grant is used by web and mobile application, and as the name states, there is an authorization code issued by the authorization server, which the client application exchanges for an access token.
A step-by-step flow for issuing an access token using the AC grant can be seen below:
User has an active session:
- The user opens a browser and accesses an application.
- The application makes an authorization request to the authorization server (AS).
- The user is already logged in and the AS issues an authorization code.
- The AS redirects the user to the application with the authorization code.
- The application exchanges the authorization code for an access token.
User does not have an active session:
- The user opens a browser and accesses an application.
- The application makes an authorization request to the authorization server (AS).
- The user is not logged in, and the AS redirects the user to the login page.
- The user authenticates with one of the configured login options.
- When the user is successfully authenticated, the AS issues an authorization code.
- The AS redirects the user back to the application with the authorization code.
- The application exchanges the authorization code for an access token.
Which API do you need?
For sending the authorization request, the authorize API is needed, and for exchanging the authorization code for an access token, the token API is required.
Example authorization request
curl --request GET \
--url 'https://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/authorize?response_type=code&client_id=myoauth2client&redirect_uri=https://www.myapp.com&scope=profile&state=dasdassd-qedsaasdd-dadas'
Example of response on the authorization request, in case the user is not authenticated
< HTTP/2 302
< location: https://www.onewelcome.com/onewelcome-dev/login/?sessionOnly=true&goto=https%3A%2F%2Fwww.iwelcome.com%2Fiwelcome-dev%2Fauth%2Foauth2.0%2Fv1%2Fauthorize%3Fresponse_type%3Dcode%26client_id%3Dmyoauth2client%26redirect_uri%3Dhttps%253A%252F%252Fwww.myapp.com%26scope%3Dprofile%26state%3Ddasdassd-qedsaasdd-dadas
Example of response on the authorization request, in case the user is authenticated
< HTTP/2 302
< location: https://www.myapp.com?code=3eccd9ca-4d1c-4584-ac31-9bb8442c7f6d&scope=profile&iss=https%3A%2F%2Fwww.onewelcome.com%2Fonewelcome-dev%2Fauth%2Foauth2.0&state=smth&client_id=myoauth2client
Example of token request
curl --request POST \
--url https://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=3eccd9ca-4d1c-4584-ac31-9bb8442c7f6d \
--data redirect_uri=https://www.myapp.com \
--data client_id=myoauth2client \
--data client_secret=somesecret
Note
Sending the grant_type=authorization_code
parameter, from the request above, in the request, indicates to the authorization server that an authorization_code
is exchanged for an access token. Keep in mind that when the authorization_code
has been used once, it becomes invalid.
OAuth 2.0 implicit grant
According to RFC6749, "the implicit grant is a simplified authorization code flow optimized for clients implemented in a browser using a scripting language such as JavaScript. In the implicit flow, instead of issuing the client an authorization code, the client is issued an access token directly."
A step-by-step flow can be seen below:
- The user opens a browser and accesses an application.
- The application makes an authorization request to the authorization server (AS).
- If the user is already logged in and the AS issues an access token, otherwise the user is redirected to the login page, and when logged in it issues an access token.
- The AS redirects the user to the application with the access token.
Which API do you need?
For the implicit grant, only the authorization endpoint is needed, since the response_type=token
indicates that the implicit grant is used.
Example authorize request
curl --request GET \
--url 'https://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/authorize?response_type=token&client_id=myoauth2client&redirect_uri=https%3A%2F%2Fwww.myapp.com&scope=email' \
--header 'Content-Type: application/x-www-form-urlencoded'
Example of response when the user is not authenticated
< HTTP/2 302
< location: https://www.onewelcome.com/onewelcome-dev/login/?sessionOnly=true&goto=https%3A%2F%2Fwww.iwelcome.com%2Fiwelcome-dev%2Fauth%2Foauth2.0%2Fv1%2Fauthorize%3Fresponse_type%3Dtoken%26client_id%3Dmyoauth2client%26redirect_uri%3Dhttps%253A%252F%252Fwww.myapp.com%26scope%3Demail
Example of response when the user is authenticated
< HTTP/2 302
< location: https://www.myapp.com#access_token=8abacc27-4eab-4c42-a30e-211d83063cbe&scope=email&iss=https%3A%2F%2Fwww.onewelcome.com%2Fauth%2Foauth2.0&token_type=Bearer&expires_in=3599&client_id=myoauth2client
Resource owner password credentials grant
The OAuth 2.0 resource owner password credentials Grant (ROPC) requires users to provide their credentials (username and password), and because of this, we recommend using this flow only when there is a high degree of trust between the resource owner and the client.
A step-by-step flow can be seen below:
- The user accesses your application and clicks login.
- The user is presented with a form for filling their credentials (username and password).
- The authorization server validates the credentials and issues an access token.
Note
For the ROPC grant, there is no redirect from the client application to the authorization server, which means that the application is calling the endpoints with the user's credentials directly.
Which API do you need?
For the ROPC grant, you need the token endpoint, and must specify in the request body that the request is an ROPC grant by sending grant_type=password
.
Example request
curl --request POST \
--url https://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=password \
--data username=myUsername \
--data password=myPassword \
--data scope=email \
--data client_id=myoauth2client \
--data client_secret=myoauth2clientPassword
Example response
{
"access_token": "d5b8468a-e1da-4b8a-826f-0b6d96860b65",
"refresh_token": "d052ddd3-bd54-4bb1-8d7e-30991a223685",
"scope": "email",
"token_type": "Bearer",
"expires_in": 3599
}
Client credentials grant
Client credentials is intended for server-side client applications, in which the client authenticates on behalf of itself.
As RFC6749 states, the client credentials grant is "used as an authorization grant typically when the client is acting on its own behalf (the client is also the resource owner) or is requesting access to protected resources based on an authorization previously arranged with the authorization server."
Note
According to RFC6749, the client credentials flow is allowed only for confidential clients.
A step-by-step flow can be seen below:
- The application sends a request to the authorization server, using its
client_id
andclient_secret
. - The authorization server issues an access token, which can be used to call different APIs.
Which APIs do you need?
For the client credentials grant, similar to the ROPC grant, only the token endpoint is needed. The difference is that the value of the grant_type
must be set to client_credentials
.
Example request
curl --request POST \
--url https://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=myoauth2client \
--data client_secret=myoauth2clientPassword \
--data scope=read:users \
Example response
{
"access_token": "9dd81f1c-4caa-40d3-a469-7897db220f22",
"token_type": "Bearer",
"expires_in": 3599,
"scope": "read:users"
}
OIDC
OIDC is an extension of OAuth2, and according to RFC, "it enables Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner."
The main difference between OAuth and OIDC is that OAuth is about authorization, and OIDC is about authentication. The definition of the authorization API that RFC 6749 specifies, states that, for the response_type
attribute, the possible values can be either token
or code
. OpenID adds a new value to the response type, which is id_token
, and allows to request in the response_type
request parameter any combination of code
, token
, and id_token
.
Note
When sending the request with response_type=id_token
, the scope
request parameter must include the value openid
.
Apart from the id_token
response type, the specification also introduced a special value, none
, which is not allowed to be sent in any combination with code
, token
, and id_token
.
As mentioned, the id_token
contains information about the authenticated user, and the properties added are referred to as claims. Not everything about the user is added in the id_token
, but only information that was requested using scopes.
For example, an authorize request with ...&response_type=id_token&scope=openid email phone
means that there should be an ID token issued, and it should have the following information or claims about the user: email
, email_verified
, phone_number_verified
, phone_number
. This means that there is a one-to-many relationship between the requested scope and the number of claims or user attributes.
Why is an id_token useful?
If you have a regular web application that you register with the OneWelcome Identity Platform, and you want to configure it to allow the user to log in with Microsoft. After the user logs in with Microsoft, an id_token
will be generated and handed over to your application. With the id_token
, you can show information about the authenticated user, such as first name, last name, and phone number, without an extra request, as is the case with OAuth2.
Example request
curl --request GET \
--url 'https://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/authorize?response_type=token%20id_token&client_id=your_app&redirect_uri=http%3A%2F%2Fyour-app.com&scope=openid%20email%20phone&state=dssadas-e33adsdsadsad-wdwq3edas-dsa&nonce=aewqeqeewqweq'
Example response
< HTTP/2 302
< location: http://your app.com#scope=email%20openid%20phone&state=something&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjM3TG1KRmk1aWNoa0RLZG81MlE4Rlc4TDFkMD0ifQ.eyJzdWIiOiJhMjZmNjc0ZS04YTg4LTQwZjgtYTZkZC1hMWE0YmJiN2M2ZGQiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImlzcyI6Imh0dHBzOi8vd3d3Lml3ZWxjb21lLmNvbS9hdXRoL29hdXRoMi4wIiwidG9rZW5OYW1lIjoiaWRfdG9rZW4iLCJwaG9uZV9udW1iZXJfdmVyaWZpZWQiOmZhbHNlLCJub25jZSI6ImFld3FlcWVld3F3ZXEiLCJhdWQiOiJ5b3VyX2FwcCIsImF6cCI6InlvdXJfYXBwIiwiYXV0aF90aW1lIjoxNjE4NTY4MzcwLCJwaG9uZV9udW1iZXIiOiIwMTM3MTIzNDU2Nzg5MGAiLCJleHAiOjE2MTg1NzE5NzYsInRva2VuVHlwZSI6IkpXVFRva2VuIiwiaWF0IjoxNjE4NTY4Mzc2LCJlbWFpbCI6Inh5ekB5b3BtYWlsLmNvbSIsInNlc3Npb24taWQiOiJlNTc2MjdlOC1hMTNhLTQ1MzgtYTFhYS0wY2UwYmRhMjYwMDkifQ.HKaRhlfaWapPxCFiIXG_bbt12KkMswxOi3j_6DTWQ5w
By decoding the JWT , you can see details about the authenticated user, along with the standard claims defined by the OpenID Connect Specification. The decoded JWT from the example above can be seen below.
Decoded JWT token
{
"sub": "a26f674e-8a88-40f8-a6dd-a1a4bbb7c6dd",
"email_verified": false,
"iss": "https://www.onewelcome.com/auth/oauth2.0",
"tokenName": "id_token",
"phone_number_verified": false,
"nonce": "aewqeqeewqweq",
"aud": "your_app",
"azp": "your_app",
"auth_time": 1618568370,
"phone_number": "01371234567890`",
"exp": 1618571976,
"tokenType": "JWTToken",
"iat": 1618568376,
"email": "xyz@yopmail.com",
"session-id": "e57627e8-a13a-4538-a1aa-0ce0bda26009"
}
What is response type none?
When the response_type
is none
, nothing is issued by the authorization server. According to the OAuth2 RFC, the purpose for this attribute is to "enable use cases where a party requests the Authorization Server to register a grant of access to a Protected Resource on behalf of a Client but requires no access credentials to be returned to the Client at that time."
The OAuth2 RFC describes the usage of this response type as when "a user wishes to purchase an application from a market, and desires to authorize application installation and grant the application access to Protected Resources in a single step. However, since the user is not presently interacting with the (not yet active) application, it is not appropriate to return access credentials simultaneously in the authorization step."
This flow requires using only the authorization API.
Example request
curl --request GET \
--url 'https://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/authorize?response_type=none&scope=email&client_id=your_app&redirect_uri=http%3A%2F%2Fyour-app.com&state=AFDvsaERwd3ed&nonce=EWAFDCaweAScxz'
Example response
< HTTP/2 302
< location: https://www.your-app.com/?scope=email&iss=https%3A%2F%2Fwww.onewelcome.com%2Fauth%2Foauth2.0&state=AFDvsaERwd3ed&client_id=your_app