Appearance
Delegated Authentication
Treezor allows you to use its OAuth industry standard authentication mechanism to authenticate your customers trourough your application.
Delegating the authentication to Treezor allows you to focus on your business while having the peace of mind provided by an expertly set up authentication mechanism.
Using Treezor as an Identity Provider means that:
- You don't have to handle passwords yourself (nor password retrievals/resets)
- You don't need to maintain a database of User credentials
- You don't need to keep up with hashing and salting best practices
- You only keep an association between the
userId
provided by Treezor authentication mechanism and the User's information in your own databases
Prerequisites – To use delegated authentication, you need
- To onboard end users with Connect – Creates their credentials in Treezor Identity Provider.
- A post-authentication URL to be declared to Connect – Where users are redirected after authenticating with Treezor.
- A private/public key pair to be generated by Treezor – The public key will be provided to you, allowing you to assert the Tokens authenticity.
Flow
Logging-in
When a User shows up to your application and doesn't have a JWT, you redirect them to a customizable login page hosted by Treezor.
The User enters their credentials and submits the login form.
If the authentication is successful, the user is redirected to a previously configured URL of your application with a code
query parameter appended by Treezor.
In and of itself, the code
doesn't allow you to authenticate the User. You will have to exchange this single-use code
for a JWT using the following request.
bash
curl -X POST {baseUrl}/oauth/token \
--form 'grant_type="authorization_code"' \ # mandatory
--form 'code="{yourTemporaryCode}"' \ # mandatory
--form 'client_id="{yourClientId}"' \ # mandatory
# --form 'scope="<SCOPE>"' # optional, if you want a specific scope
1
2
3
4
5
2
3
4
5
Returns an object containing the User's JWT.
json
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "{theUsersAccessToken}",
"refresh_token": "{theTokenAllowingForJwtRefresh}"
}
1
2
3
4
5
6
2
3
4
5
6
The User can now add this access_token
in the Authentication
header of all requests made to your application so that you can authenticate them.
Authenticating
To authenticate an End User, you must:
Asserting the JWT legitimacy
Security – Ensure your application validates the JWT legitimacy
Your must implement and test this step with great care. Were your application to accidentally accept invalid tokens would leave it open to anyone.
To check that the token is legitimate, you will use:
- The User's JWT Token,
- The
RSASSA_PKCS1_V1_5_SHA_256
algorithm, - Your Connect public key.
The User's JWT is composed of three sections each encoded in base64 and separated by dots.
- The second section is the token payload
- The last section is the token signature
Consider the following JWT, as provided by your User in the Authentication
header.
json
eyJ0eXAiOiJKV1QiLCJhbGciOiJSU0FTU0FfUEtDUzFfVjFfNV9TSEFfMjU2In0.eyJpc3MiOiJ0cmVlem9yX2Nvbm5lY3QiLCJpYXQiOjE2MzM1MTMyMjEsImV4cCI6MTYzMzUxNjgyMSwic3ViIjoiNzkwMzdlNmUtYzFlMS00MmYyLWJlOWEtZTI0OWM3NjdjNDc2Iiwic2NvcGUiOlsiYWRtaW4iLCJrZXlzIiwibGVnYWwiLCJyZWFkX29ubHkiLCJyZWFkX3dyaXRlIiwicmVhZF9hbGwiXSwidXNlcklkIjpudWxsLCJjYXJkcyI6W10sIndhbGxldHMiOltdLCJjaGlsZHJlbiI6W10sInVzZXJUeXBlIjoiYXBwbGljYXRpb24iLCJjbGllbnRJZCI6IjkyOTI1MiJ9.cPWi6RY1n0tPIJ1jG8600wZQvMUU1eIZPq1uzIju7OI8SnJ77FBmj25q8w0JcUwGIZf0GDKI51tovi0aqFNZsVrsP1V8o3b_5eJiEA2LtUVimAyWWtheMEa1J5Seqh3_rH5BO0xos2fRXM6CyFK1xDwc5EJeD0Pko5Yq3ls4-bcJt3yYBPH3JkaaADt2ettYATnpv9KnBeTPU7INDwNd2d6orVdc0yUgx9dmO9-NPbYBQuNsPTDOV8nnCWu6P0RAqUdjDZKbrr71Vj61ULur5yIr0oHLYg--80p6mgrMMAbPHQTKHO-wrcA94NvTCQ_5STXxUVfxh34xbOotdmeUeQ
1
You encrypt the payload using the RSASSA_PKCS1_V1_5_SHA_256
algorithm and Connect public key.
bash
# an example will soon be provided
aws kms sign \
--key-id '{connectPublicKey}' \
--signing-algorithm RSASSA_PKCS1_V1_5_SHA_256 \
--message '{payload}'
1
2
3
4
5
2
3
4
5
You then compare the newly generated signature with the JWT signature.
- If they match: you can proceed to the next step.
- If they do not match:
- Deny any access to your application,
- Consider the event as a potential attack and take appropriate measures.
Extracting the User's identity
As you now can trust the token Payload, simply use a base64 decoding function on the token second section (payload).
bash
base64 -d "eyJpc3MiOiJ0cmVlem9yX2Nvbm5lY3QiLCJpYXQiOjE2MzM1MTMyMjEsImV4cCI6MTYzMzUxNjgyMSwic3ViIjoiNzkwMzdlNmUtYzFlMS00MmYyLWJlOWEtZTI0OWM3NjdjNDc2Iiwic2NvcGUiOlsiYWRtaW4iLCJrZXlzIiwibGVnYWwiLCJyZWFkX29ubHkiLCJyZWFkX3dyaXRlIiwicmVhZF9hbGwiXSwidXNlcklkIjpudWxsLCJjYXJkcyI6W10sIndhbGxldHMiOltdLCJjaGlsZHJlbiI6W10sInVzZXJUeXBlIjoiYXBwbGljYXRpb24iLCJjbGllbnRJZCI6IjkyOTI1MiJ9"
1
Returns the decoded payload.
json
{
"iss": "treezor_connect",
"iat": 1624439479,
"exp": 1624443079,
"sub": "79037e6e-c1e1-42f2-be9a-e249c767c476", // here is the trzConnectUserId
"scope": [
"keys",
"legal",
"read_only",
"read_write",
"read_all"
],
"userId": {userId}, // here is the userId
"clientId": {yourClientId},
"cards": [],
"wallets": [],
"children": [],
"userType": "user"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Note that two distinct IDs are contained in this object:
userId
used across the Treezor API to identify the User (to use to match Connect Users with your locally stored Users).sub
(trzConnectUserId
) used initially during the Connect Onboarding, and when changing password.
It is very important to store the userId
as a string since userId
will be migrated to UUID in the future.
Now you could for example retrieve your locally stored User using the following pseudocode:
java
try {
// assert that the JWT signature is valid
// and retrieve trzConnectUserId from the JWT payload
connectUserId = JWT
.assertSignatureIntegrity()
.decodePayload()
.getConnectUserId()
}
catch(Exception authenticationError) {
// The JWT has an invalid signature, forbid access and terminate
App.die(authenticationError.toString(), 403)
}
// retrieve the locally stored User from your database
customer = Customers.getByConnectUserId(connectUserId)
// perform any action necessary : display wallets balances, recent operations, etc.
wallets = customer.getWallets()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Reading – Learn more about OAuth
You may find OAuth website helpful in implementing Treezor's OAuth Identity Provider.