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 and client_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.

2557

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.