Custom Auth
Custom Auth Provider
For cases where you have a custom SSO and need to introspect third-party token
or cookie
and receive access/refresh token
custom auth provider can be used.
Custom auth provider is a part of frappe_utils and can be installed as a frappe app.
Example usecase
Lets consider a case were we have a third party SSO that returns user with a cookie once logged in.
Lets register this SSO provider as Custom Auth Provider
and configure its introspection.
Field | Options | Description |
---|---|---|
Enable | Flag | Enable/Disable provider |
Method | GET/PUT/POST | Method that SSO introspection accepts |
Endpoint | Introspection URL | SSO Provider Endpoint that the request should be made against |
Header Token Type | Cookie/Token/Custom | Type of Authorization header |
Header Token Key | Token Key | What header key should be token/cookie/custom be picked up from. |
Response Email Map | Email key path | "." path to the email key in introspection response. If response will be {data: {email: "example@castlecraft.in" }}} then your key should be data.email |
OAuth Client | Frappe OAuth Client | Linked OAuth client that the token would be generated against |
Referer | URL | Referer key value would be verified against the the HTTP Referer |
Create User | Flag | Create a new user if user not found |
New User Name Map | User Name Path | "." path to the user name key in introspection response. If response will be {data: {full_name: "CEPL User" }}} then your key should be data.full_name |
Roles | Table | Default roles that should be assigned to newly created user |
How to use?
Above configured custom provider can be used consumed as follows
CURL Request
curl http://$YOUR_SITE/api/method/frappe_utils.auth.validate \
-H 'X-FRAPPE-CUSTOM-HEADER: $CUSTOM_PROVIDER_NAME' \
-H 'Cookie: $COOKIE_KEY=67035c53b49543d1336e4369b4201917fa808b19a019d5a44225ae88' \
-H '$TOKEN_KEY: 67035c53b49543d1336e4369b4201917fa808b19a019d5a44225ae88' \
-H 'Referer: $EXPECTED_REFERER'
Following request should give you a frappe token for the user
linked to provided cookie/token
.
CURL Response
{
"access_token": "cf2c7650b6d7159ffb0d225ac1a33e",
"refresh_token": "d6a0b34fa256149af536952cde0e3a",
"expires_in": 3600
}
Permission Rules
The Permission Rules table
enables the assignment of permissions to users based on specified conditions. The provided condition
if evaluated and true, the corresponding Permission Rule
are assigned.
Select the appropriate Permission Rule
value from the Permission Rules List.
Enter the desired condition
for evaluation using the following syntax:
Examples
User we want to create Permission Rule A
only when user has domain_id
:
Permission Rule |
Condiion |
---|---|
Permission Rule A | payload['data']['domain_id'] |
Above permission rule will only be created when domain_id
is present in provider response.
User we want to create Permission Rule B
only when belongs to a country country
:
Permission Rule |
Condiion |
---|---|
Permission Rule A | payload['data']['domain_id'] |
Permission Rule B | payload['data']['country'] === "India" |
Above permission rule will only be created when country
is india for provider response.
User Mapping
User mapping is for cases when addition mapping is needed around setting user fields dynamically from the response.
Examples
User we want set First Name
and Last Name
of use separately from incoming full_name
:
Example incoming full-name: Prafful Suthar
, Nishith Singh
, etc hence following configuration could be added to achieve this
User Field |
Mapping |
---|---|
First Name | payload['data']['full_name'].split(" ")[0] |
Last Name | payload['data']['full_name'].split(" ")[1] |
User we want set Language
from incoming country
or have a default to English
:
Example incoming country: India
, Null/None
, etc hence following configuration could be added to achieve this
User Field |
Mapping |
---|---|
Language | "Hindi" if payload['data']['country'] == "India" else "English" |
Note:
Utilize the variable payload
to access API response data for Permission Rule Table
and User Mapping Table
.
Redirect URL
Implementation
Step 1: Enter Redirect URL
To enable redirection after validation, users should enter the desired URL in the "Redirect URL" field. This URL will determine where users are redirected after successful authentication.
Step 2: Validate Endpoint
When a user tries to authenticate, instead of directly returning the token, we'll check if the "Redirect URL" field is present for the user.
- If the "Redirect URL" field is present:
- Token generated will be base64 encoded JSON string
- Redirect the user to the specified URL with the token as a parameter.
Example
Let's consider an example:
- Custom Provider with Redirect URL: "https://something.com/callback"
After generating the token user will redirect to:
-
https://something.com/callback?token=eyJhY2Nlc3NfdG9rZW4iOiAieCIsICJyZWZyZXNoX3Rva2VuOiJZIiwuLn0=
-
Received token can be caught on callback and decoded for complete token response
-
How to decode token?
token = `eyJhY2Nlc3NfdG9rZW4iOiAiY2FmZjc2NGI5MDJmYjQzYjYwNmY5YmNmZjE4M2Y4IiwgInRva2VuX3R5cGUiOiAiQmVhcmVyIiwgImV4cGlyZXNfaW4iOiAzNjAwLCAicmVmcmVzaF90b2tlbiI6ICJiMWE5YWE0NjBhMzQ4NWUwOWQ3MWQxM2Y4MGI1NmMiLCAiZW1haWwiOiAiYW5vbnltb3VzLnVzZXJAZXhhbXBsZS5jb20ifQ==`
decoded_token = JSON.parse(atob(token))
- Decoded Token
{
"access_token": "caff764b902fb43b606f9bcff183f8",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "b1a9aa460a3485e09d71d13f80b56c",
"email": "anonymous.user@example.com"
}
"Custom" type token
This specific type is for scenarios requiring customized authorization token and cookie, where dynamic header and cookie configurations are essential.
In recent integration we faced a case where user wanted to send Authorization: Bearer <X>
as header to custom auth provider, following did not work as frappe middleware work with same header configurations
Hence a custom way is needed when you need to send headers bypassing frappe layer.
Example.
Lets consider a use-case where i want to send following header and cookie to my provider
Header
'Authorization': 'Bearer TOKEN',
Cookie
'cookie': "MYSAPSSO2=ABC"
For sending above token and/or cookie you need to encode above header as follows (paste below in browser console)
my_header = {
// if you need header
'header' : {
'Authorization': 'Bearer TOKEN',
},
// if you need cookie
'cookie': "MYSAPSSO2=ABC"
}
value = btoa(JSON.stringify(my_header))
// log it
console.log("This is your ENCODED_TOKEN: ",value)
// copy it
copy(value)
Above will give you encoded headers
.
Append above encoded headers
to your get token request
curl http://$YOUR_SITE/api/method/frappe_utils.auth.validate \
-H 'X-FRAPPE-CUSTOM-HEADER: $CUSTOM_PROVIDER_NAME' \
-H 'X-FRAPPE-CUSTOM-VALUE: $ENCODED_TOKEN' \
-H 'Referer: $EXPECTED_REFERER'
Following request should return you frappe token for respective user.
{
"access_token": "cf2c7650b6d7159ffb0d225ac1a33e",
"refresh_token": "d6a0b34fa256149af536952cde0e3a",
"expires_in": 3600
}