OAuth 2.0 - Resource Owner Password Credentials grant
Overview
NOTE: Resource Owner Password Credentials Grant will be deprecated in OAuth 2.1. Please think twice before using this.
The Resource Owner Password Credentials Grant (defined in RFC 6749, section 4.3) can be used directly as an authorization grant to obtain an access token, and optionally a refresh token. This grant should only be used when there is a high degree of trust between the user and the client and when other authorization flows are not available.
This grant type can eliminate the need for the client to store the user credentials for future use, by exchanging the credentials with a long-lived access token or refresh token.
How to implement the Resource Owner Password Credentials
Client's Grant Type
The client's grant type property must be to password.
Register an Identify local user
You need to create a new Identify user:
From the Safewhere Admin application list, you can create an OAuth2.0 application, then open its sub tabs and update the following:
- On its connection tab:
- Client ID: Specifies the unique ID of the application. Client ID is case-sensitive.
- Client secret: Specifies the Client secret of the application. Client secret is case-sensitive.
- Token endpoint authentication method: Specifies the client authentication method to the token endpoint.
- Allowed Callback URIs: Specifies the redirect URL after successful authentication, e.g
https://identifydomain/runtime/
- Application name: Specifies the name of the application
- Security token audiences: Specifies the recipients (usually in URI format) that issued access tokens are intended for. When the resource parameter is missing, an access token is issued with its 'aud' claim set to all configured audiences.
- On its security tab:
- JWS algorithm: Either RSASigning or HMACSymmetric.
- Symmetric signing key: Used to generate a HMAC Symmetric signing key; key can be 32-byte, 48-byte, or 64-byte. You can then either copy the key and paste it to the configuration or check the appropriate check box and click Select key to apply it.
- Allow password flow: This setting must be True.
- Client ID: specifies the unique ID of the application. Client ID is case-sensitive.
- client secret: specifies the client secret of the application. Client secret is case-sensitive.
- Token endpoint authentication method: specifies the client authentication method to the token endpoint.
- Allowed Callback URIs: specifies the redirect URL after successful authentication, e.g.
https://identifydomain/runtime/
- Application name: specifies the name of the application
- Security token audiences: Specifies the recipients (usually in URI format) that issued access tokens are intended for. When the resource parameter is missing, access tokens are issued for all configured audiences.
Security tab:
- JWS algorithm: either RSASigning or HMACSymmetric.
- Symmetric signing key: used to generate a HMAC Symmetric signing key; key can be 32-byte, 48-byte, or 64-byte. You can then either copy the key and paste it to the configuration or check the appropriate check box and click Select key to apply it.
- Allow password flow: this setting must be True.
Ask for a token
To ask Identify for tokens for any of your authorized client applications, perform a POST operation to the token endpoint:
https://#identifydomain/runtime/oauth2/token.idp
URI parameters:
Parameter | Description |
---|---|
client_id | Your application's client ID |
client_secret | Your application's client secret |
grant_type | This must be "password" |
username | The Identify username |
password | The Identify user password to login to the Identify |
The response contains a signed JSON Web Token, the token's type (which is Bearer), and in how much time it expires in Unix time (3600 seconds, which means 1 hour).
{"scope":"identify*empty","token_type":"Bearer","access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IkNVYjM4QjMzMjZ4TkI4RFRVN1JkZjhyWkJYNCIsIng1dCI6IkNVYjM4QjMzMjZ4TkI4RFRVN1JkZjhyWkJYNCIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImlkZW50aWZ5dXNlcjEiLCJzdWIiOiJpZGVudGlmeXVzZXIxIiwibmFtZSI6ImlkZW50aWZ5dXNlcjEiLCJ1cm46aW50ZXJuYWw6dXNlcmlkIjoiZjYwNzU2ZjYtM2Y4Zi00NzIzLWFkNTItMjgyYjAwZDdlMGFhIiwidG9rZW5fdXNhZ2UiOiJhY2Nlc3NfdG9rZW4iLCJqdGkiOiIyYjk0YTg4NC0xY2VmLTRmMmItOGYzZi0wY2Q5MDlhNzllNTMiLCJzY29wZSI6ImlkZW50aWZ5KmVtcHR5IiwiYXVkIjoiaHR0cHM6Ly9pZHBtYXN0ZXI2MC5zYWZld2hlcmUubG9jYWwvcnVudGltZS8iLCJhenAiOiJjbGllbnRfY29ubmVjdF9zYW1wbGVfaWQxIiwiaWF0IjoxNTkwMzc0OTI1LCJuYmYiOjE1OTAzNzQ5MjUsImV4cCI6MTU5MDM3ODUyNSwiaXNzIjoiaHR0cHM6Ly9pZHBtYXN0ZXI2MC5zYWZld2hlcmUubG9jYWwvcnVudGltZS9vYXV0aDIifQ.LMYREmlcX41mmO8XfzL1VOZGqcHOejbyOzu2jcrGq9XLksTn3md7f2OOgoXPPzK0Pd2oB18240sjQvtshmy2ZGIcNXMF7SelFXQpkLigRxm4mu1rWNLBA7gN3vOiU3kMryO82OXmKU81PbPQ565ji8Wf7tqmGiXHIRmkz_YEr9u3JASycOIP6uIFqk8sjbPd4KEna_98YXeN5MEdDPP9C-vV2JmWLBTzigg3eoVzCNh5ga5yx5Gbhsw8b0EIM3SSYL38hIodGUWBMfWMaxLvmXyqVyVMp5T7XHu8Cdz-8fpL1fDUh5DPyFMI4x2CJNpnRvyOlv7H9c1QI5R1FVrH5g","expires_in":3600}
If you decode the access_token, you will see that it contains the following claims:
{
"unique_name": "identifyuser1",
"sub": "identifyuser1",
"name": "identifyuser1",
"urn:internal:userid": "f60756f6-3f8f-4723-ad52-282b00d7e0aa",
"token_usage": "access_token",
"jti": "2b94a884-1cef-4f2b-8f3f-0cd909a79e53",
"scope": "identify*empty",
"aud": "https://idpmaster60.safewhere.local/runtime/",
"azp": "client_connect_sample_id1",
"iat": 1590374925,
"nbf": 1590374925,
"exp": 1590378525,
"iss": "https://idpmaster60.safewhere.local/runtime/oauth2"
}
FAQ
Q: I would like to include the refresh_token on the response. What can I do?
A: you can enable the "Allow refresh token" setting at the security tab of the OAuth2.0 application connection.
Here is a sample for the response:
{"scope":"offline_access","token_type":"Bearer","access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IkNVYjM4QjMzMjZ4TkI4RFRVN1JkZjhyWkJYNCIsIng1dCI6IkNVYjM4QjMzMjZ4TkI4RFRVN1JkZjhyWkJYNCIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImlkZW50aWZ5dXNlcjEiLCJzdWIiOiJpZGVudGlmeXVzZXIxIiwibmFtZSI6ImlkZW50aWZ5dXNlcjEiLCJ1cm46aW50ZXJuYWw6dXNlcmlkIjoiZjYwNzU2ZjYtM2Y4Zi00NzIzLWFkNTItMjgyYjAwZDdlMGFhIiwidG9rZW5fdXNhZ2UiOiJhY2Nlc3NfdG9rZW4iLCJqdGkiOiI2ZTgzNDA2MC0yZTI3LTQzOWItYjYyNS1iNWQ3OGFlMWFmYmYiLCJzY29wZSI6Im9mZmxpbmVfYWNjZXNzIiwiYXVkIjoiaHR0cHM6Ly9pZHBtYXN0ZXI2MC5zYWZld2hlcmUubG9jYWwvcnVudGltZS8iLCJhenAiOiJjbGllbnRfY29ubmVjdF9zYW1wbGVfaWQxIiwiaWF0IjoxNTkwMzc1MjgyLCJuYmYiOjE1OTAzNzUyODIsImV4cCI6MTU5MDM3ODg4MiwiaXNzIjoiaHR0cHM6Ly9pZHBtYXN0ZXI2MC5zYWZld2hlcmUubG9jYWwvcnVudGltZS9vYXV0aDIifQ.Ajlec08BkcCMEt5Eu6NVXTjdjFuKXF7uaoSpWAUhXrWvpDB0z3sbdAfvbMe6AP0dGpobdEA12iUHfuR21236lQVDSuhbxvm7ICELx6MQvlBJ7XlKbSRgRdhne1YIWEQz36oMJf1drjFTMYg5TV2qtiSibacwoeq3mY14rNjia9IOWY4Q3GGVAEHEAvK-G7WpSyz1zt9c6xeEHNutaj1YYFjzECky3a_Zvit35JtzBMKl-Z4m10CpaEfsvlL38rS_zjSL9wogwMPhNBH7csVZiZWAIN3lmIrG2BT95h1ljNQxLysfuQM8NyuZVnCrDauQI6rZm6gUbTIIYFCzn9LGXg","expires_in":3600,"refresh_token":"CfDJ8KrDPVA8MR9KlwiBR7scgzY9lAtgPE9GtKs1s-H5_48IZDypUFx0Nm4dHHJHYgYGKQIukH1MLwPn1EVGNwVQK9y0LNjr5Gxk7Os3Dg-2pFVBwNW1zUucmN6mZaJi9vFxQ3BTQleRzSCu01stauoF3IUPYAW3WbaWq9dVRjvL02GY5itb8QrXidzEK9z6l8tj1iWKR0CRq4LTv7F6j11wc5crqUL0cFk6_ktvpvBl9yVC3Cb-D3LVEqSjxaRm0W0Ux0GOOYXzYaqN-sN0LOenYiKlQmRND06kDlIBZPYRF1kz121F5xRUJShLSM8X3Enr1Sx9DZAkbOFGh7kTYKktFOSz0TN-eiqC3qFbl56cUP71IaKqrzTshNhobenDElnyImJnseNXOgm71F-G7OfS83Nbi5U_LKH6XpVY3-pdz1gTjC-Ppjxg0UlXfAOhPQpZQTDFHmToZrU9RMZaWTsUj115rbiWQCYrHEjdpaDOeMlJ1CiNE9lEQaB7Gd_gjMM3mzdQLobT59DV2P99W5BqQ3yDcc1JvS2Lv2vH4eBO7zgdeeSxjBvWKKdGboIZ_aFV6gnppFsVzJ471Vl2mt4CiecWDECEkdvINfCx1RDNhcqBy4j3UgSRPkKmQ9TddHqhiwhCwyMJ4TttoFCSIW939_gU2sxS0hzqC1UxDLbnfVW2Q18hcJDRiL848G3kv7TDRQ-WTnHgGUV_C55BoUxyBjlLH6ekImKFmDq7txZaW01TGtcg0NcQLa5e3jLgMIS5bImFnseOs1nLjgV7yEbEGPbOQiL0fPNWbs7VS3_v05XZotcgxj90TWyEK4_3fTNBeNVGI-LVBxDXhAwCwiL4pDpKmNBYbTIwIWnb4_VVzItDyp_ViAB7KXCDBg1r4ozqUV5ZBN36IKzgtkqFxtUYg-rHAwuTlZlRrAKIvyLccOKmPkWYvXEEptsDSEDFDuYqQOrSCMMrVOHYK1UdTBDln4s"}
Q: I want to use the "dk:gov:saml:attribute:CprNumberIdentifier" claim type for username, not the Name claim type. What can I do?
A: You can follow these steps:
- You create the Identify local user who has the value of the "dk:gov:saml:attribute:CprNumberIdentifier" claim.
- You create a NameID transformation whose source is "dk:gov:saml:attribute:CprNumberIdentifier"
- You apply the claim transformation to the OAuth2.0 application
Here is the sample result:
{"scope":"identify*empty","token_type":"Bearer","access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IkNVYjM4QjMzMjZ4TkI4RFRVN1JkZjhyWkJYNCIsIng1dCI6IkNVYjM4QjMzMjZ4TkI4RFRVN1JkZjhyWkJYNCIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImFkbWluIiwic3ViIjoiMTIzNDU2NzgiLCJkazpnb3Y6c2FtbDphdHRyaWJ1dGU6Q3ByTnVtYmVySWRlbnRpZmllciI6IjEyMzQ1Njc4IiwidXJuOmFueWlkOnJvbGUiOiJBZG1pbmlzdHJhdG9yIiwidXJuOmlkZW50aWZ5OnJlc3QtYXBpOnJvbGUiOiJBZG1pbmlzdHJhdG9yIiwicm9sZSI6WyJDbGFpbUFkbWluIiwiQ2xhaW1UcmFuc2Zvcm1hdGlvbkFkbWluIiwiQ29ubmVjdGlvbkFkbWluIiwiR3JvdXBBZG1pbiIsIklkZW50aWZ5IFNlcnZpY2UiLCJPcmdhbml6YXRpb25BZG1pbiIsIlN5c3RlbVNldHVwQWRtaW4iLCJVc2VyQWRtaW4iXSwibmFtZSI6IjEyMzQ1Njc4IiwidXJuOmludGVybmFsOnVzZXJpZCI6ImNhN2I0OGFjLTgzMGYtNDEyNi1iZGMyLTdhYmM3N2JmNDg4YSIsInRva2VuX3VzYWdlIjoiYWNjZXNzX3Rva2VuIiwianRpIjoiZTRmMDYyNWEtZjU3YS00M2IxLThiNzctY2U3ZDAxNTE4ZTA5Iiwic2NvcGUiOiJpZGVudGlmeSplbXB0eSIsImF1ZCI6Imh0dHBzOi8vaWRwbWFzdGVyNjAuc2FmZXdoZXJlLmxvY2FsL3J1bnRpbWUvIiwiYXpwIjoiY2xpZW50X2Nvbm5lY3Rfc2FtcGxlX2lkMSIsImlhdCI6MTU5MDM4OTM1NSwibmJmIjoxNTkwMzg5MzU1LCJleHAiOjE1OTAzOTI5NTUsImlzcyI6Imh0dHBzOi8vaWRwbWFzdGVyNjAuc2FmZXdoZXJlLmxvY2FsL3J1bnRpbWUvb2F1dGgyIn0.xNofD1xAn-ybGlXhi-eoWmBvslA3ftm4LaQkWK09aBGpGtYhjF9yMPubQCjUHcfrZdzruHsid8nHB26y_3IWXRQalLTIwRqRxRC_JIOX4MjED9OF2NNh8ARYH4Y5SXOjwat1lxA3VYziB-DexqajaiFTDSvmgXh4JMqkqMxce3tgkdfS_VMFcetpgt7mLgFKYffvefXGOHzAXBFh6x_4TnPw-dzZEIhijYJBKfLxoEZzEcASrEZzu-8e8WYMbFFstLJHlagbn-pbPvW40VIADGoro9AeA0qWxmcpEVHmg6yW4LBtRa6mcbDmwcVXqN9NK-IDPmSG3icXdhPSxfhNVg","expires_in":3600}
If you decode the access_token you will see that it contains the following claims:
{
"unique_name": "admin",
"sub": "12345678",
"dk:gov:saml:attribute:CprNumberIdentifier": "12345678",
"urn:anyid:role": "Administrator",
"urn:identify:rest-api:role": "Administrator",
"role": [
"Identify Service",
"OrganizationAdmin",
"SystemSetupAdmin",
"UserAdmin"
],
"name": "12345678",
"urn:internal:userid": "ca7b48ac-830f-4126-bdc2-7abc77bf488a",
"token_usage": "access_token",
"jti": "e4f0625a-f57a-43b1-8b77-ce7d01518e09",
"scope": "identify*empty",
"aud": "https://idpmaster60.safewhere.local/runtime/",
"azp": "client_connect_sample_id1",
"iat": 1590389355,
"nbf": 1590389355,
"exp": 1590392955,
"iss": "https://idpmaster60.safewhere.local/runtime/oauth2"
}