OAuth2
OAuth2 enables third-party applications to authenticate users and get data from the Shine API.
If you don't have any credentials yet, the first thing to get started is to fill this form. We will send your
client_id
andclient_secret
once your request is accepted.
URLs
Base authorization URL: api.shine.fr/v2/authentication/oauth2/authorize
Token URL: api.shine.fr/v2/authentication/oauth2/token
Revocation URL: api.shine.fr/v2/authentication/token/revoke
Security considerations
To prevent security vulnerabilities like Cross Site Request Forgery, CSRF, or Clickjacking we strongly recommend you to use an additional state
parameter that should be a value that binds the user's request to their authenticated state. For example, state
could be a hash of the user's session cookie, or something else that can be linked to the user's session.
On the client side, before beginning the authorization flow, generate a state
that is unique to that user's request. The value should be stored somewhere only accessible to the client and the user (same-origin policy). When the user is redirected, the state
parameter is returned. The client validates the request by checking that the state
returned matches the stored value. If they match, it is a valid authorization request. If they do not match, it's possible that someone intercepted the request and the request should be denied.
While Shine does not require the use of the
state
parameter, we highly recommend that you implement it for the security of your own applications and users' data.
For details on how to implement OAuth2 please see RFC 6749 or any online articles considering your app language.
Authorization Flow (Code Grant)
This is the grant type most often associated with OAuth: Code Grant allows the authorization server to act as an intermediary between the client (your server) and the resource owner (the user), so the resource owner's credentials are never shared directly with the client. We decided to only support the Code Grant flow for improved security.
Step 1 - Ask users to authorize your app
To connect with shine, your web or mobile app should redirect users to the following URL:
https://api.shine.fr/v2/authentication/oauth2/authorize
With the following GET parameters values:
client_id:
Your application's client_id
scope:
A list of available scopes separated by encoded spaces (%20)
redirect_uri:
The redirection URL with which you registered your application
state:
Unique string to be passed back upon completion (see Security Considerations)
Authorization URL Example
https://api.shine.fr/v2/authentication/oauth2/authorize?client_id=127332580432496061&scope=openid%20bank:transfers:write&state=QS9DkxQS1ZEDSQKD&redirect_uri=https%3A%2F%2Fyou.com
The user will be prompted to authorize your application for the requested scopes. On acceptance, they will be redirected to your redirect_uri
.
Step 2 - Redirect users to your server with a verification code
If the user authorized your app, we will redirect him back to your redirect_uri
with a temporary code in a code
GET parameter, as well as a state
parameter if previously sent to the authorization endpoint. As specified in the "Security Considerations", you should check the state with the one you stored. If the states don't match, the request may be malicious and you should stop the process.
Redirect URL example
https://yourapp.com/?code=PxAvx90lLFc8gLNaaLoj9l7Ku7bEEcee&state=QS9DkxQS1ZEDSQKD
Step 3 - Exchanging a verification code for an access token
You can now exchange the verification code to get an access token by making a POST request to the token URL https://api.shine.fr/v2/authentication/oauth2/token
with the following parameters passed in the request's body:
client_id
- your application's client id
client_secret
- your application's client secret
grant_type
- must be set to authorization_code
code
- the code from the querystring
redirect_uri
- your redirect_uri
Access token example
import axios from 'axios';
const API_OAUTH_ENDPOINT = 'https://api.shine.fr/v2/authentication/oauth2';
const CLIENT_ID = '127332580432496061';
const CLIENT_SECRET = 'Losq!21ksqç012kkxlApOOix198x1';
const REDIRECT_URI = 'https://yourapp.com';
const requestAccessToken = (code) => {
const body = {
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': REDIRECT_URI
}
const headers = {
'Content-Type': 'application/json'
}
return axios.post(`${API_OAUTH_ENDPOINT}/token`, body, { headers });
}
In response, you will receive:
{
"access_token": "XXXXXXXXXX8AOixpaiId872XXXXXXXX",
"token_type": "Bearer",
"id_token": "XXXXXXXXXXQA9SJxiQ921XXXXXXXX",
// only if openid is required in scope
"expires_in": 604800,
"refresh_token": "XXXXXXXXXX9819x74590poXXXXXXXX",
"scope": "openid bank:transfers.write",
"metadata": {
"companyProfileId": "XXXXXXXXXX3472g48591qeXXXXXXXX",
"companyUserId": "XXXXXXXXXX8135j72946fsXXXXXXXX",
"uid": "XXXXXXXXXX6239k48257moXXXXXXXX"
}
}
metadata
field contains the user's uid
, companyProfileId
and companyUserId
.
You might need these values for subsequent requests.
With the users's access token you can make certain requests to the API on their behalf, depending on the scopes you requested.
expires_in
represents how long until the returned access token expires, in seconds. You will need to anticipate the token expiration and refresh it if needed. To refresh, you will need to make another POST request to the token URL https://api.shine.fr/v2/authentication/oauth2/token
with the following parameters passed in the request's body:
client_id
- your application's client id
client_secret
- your application's client secret
grant_type
- must be set to refresh_token refresh_token
- the user's refresh token
redirect_uri
- your redirect_uri
Refresh Token Exchange Example
import axios from 'axios';
const API_OAUTH_ENDPOINT = 'https://api.shine.fr/v2/authentication/oauth2';
const CLIENT_ID = '127332580432496061';
const CLIENT_SECRET = 'Losq!21ksqç012kkxlApOOix198x1';
const REDIRECT_URI = 'https://yourapp.com';
const refreshToken = (refreshToken) => {
const body = {
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'refresh_token',
'refresh_token': refreshToken,
}
const headers = {
'Content-Type': 'application/json'
}
return axios.post(`${API_OAUTH_ENDPOINT}/token`, body, { headers });
}
ID Token
As specified in the Open Id Specification, you can require an id_token
if you ask for the "openid" scope. You can rely on this token to create accounts and authenticate users without asking for password like with Google or Facebook Connect.
The id_token
is a JWT signed using JSON Web Key Set (JWKS) that contains user profile informations, in the form of claims that you need to decode. How to precisely decode and validate a JWT is out of this documentation scope as it depends on your language and backend implementation. You can find more informations on jwt.io. We strongly recommend to validate id_token
as it can be intercepted or altered by third-parties. We use RS256 and JWKS to sign our tokens and you can get the public JWKS key on https://api.shine.fr/v2/authentication/oauth2/.well-known/jwks.json
to verify the JWT signature.
Please note that our JWKS key can be rotated.
You should also validate the claims once decoded:
exp
: timestamp, must be greater than the current timestamp.
iss
: token issuer, must be https://accounts.shine.fr
ID Token Content
{
iss: 'https://accounts.shine.fr',
aud: your client_id,
sub: string, shine uniq user id,
exp: timestamp, token expire at,
iat: timestamp, token issued at,
// if "email" scope asked
email: user email,
email_verified: true or false,
// if "phone" scope asked
phone: '+336808080',
// if "profile" scope asked
name: user full name,
given_name: user first name,
family_name: user last name,
birthdate: ISO 8601:2004, YYYY-MM-DD format,
gender: male or female,
picture: url of user picture,
locale: user locale, represented as BCP47 tag (fr-FR, en-US...),
updated_at: last user profile update timestamp,
zone_info: string representing user time zone (Europe/Paris, America/Los_Angeles...).
}
Request Denied
If the user do not allow your request, we will redirect him back to your redirect_uri
with an error parameter as follow:
https://you.com?error=access_denied&state=QS9DkxQS1ZEDSQKD
Using AccessToken
To communicate with our API, you need to pass your access tokens, also known as bearer tokens, in the HTTP Authorization
header as follow:
GET https://api.shine.fr/v2/bank/accounts
Authorization: Bearer XXXXX9E38Sksq29XXXXXX
Revoking Tokens
If you or the user want to remove your app access, or change the requested scopes, you need to revoke the last refresh token using a POST request to the revoke token URL https://api.shine.fr/v2/authentication/oauth2/token/revoke
with the following parameters in the request's body:
client_id
- your application's client id
client_secret
- your application's client secret
token
- the refresh_token
you want to revoke
Revoking Token Example
import axios from 'axios';
const API_OAUTH_ENDPOINT = 'https://api.shine.fr/v2/authentication/oauth2';
const CLIENT_ID = '127332580432496061';
const CLIENT_SECRET = 'Losq!21ksqç012kkxlApOOix198x1';
const revokeToken = (refreshToken) => {
const body = {
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'token': refreshToken,
}
const headers = {
'Content-Type': 'application/json'
}
return axios.post(`${API_OAUTH_ENDPOINT}/token/revoke`, body, { headers });
}
Revoking the refresh token will also revoke the access token. If you want to re-authenticate, you will need to start over the oauth2 flow to get new tokens.
Updated over 1 year ago