Obtaining an Access Token
How to write a client using Oauth2 Signed Assertions (JWT profile) authentication/authorization
1. Request the token from the Authorization Server
- An HTTP POST request to the endpoint /oauth/v2/token in accordance with RFC 7521 section 4.2 and the specifications referenced below.
- The body of the request should include the following parameters
- grant_type=client_credentials as specified in RFC 6749 section 4.4.2
- client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer as specified in RFC 7523 section 2.2 and section 8.1
- client_assertion=eyJhbGciOiJSUzI1NiIsI.eyJpc3Mi.cC4hiUPo which is the signed JWT as described in RFC 7519
- code=value where value is a random string generated by the API client for CSRF protection.
- The body should be encoded using the "application/x-www-form-urlencoded" encoding algorithm as specified in RFC 6749 appendix B.
- An example request is shown in RFC 7523 section 2.2.
- The value of the client_assertion parameter is created by creating a JWT in accordance with: RFC 7523 section 2.3
- The following claims must be in the JWT
- iss: The issuer of the JWT. We don't currently do anything with the issuer value. However, it must be present.
- sub: The sub value must be the client_id. The client_id should match an ApiUser.lookup_code.
- aud: The audience value must match the hostname of the Authorization Server.
- exp: The expiration time of the JWT. The time must not be in the past.
- jti: See specification for details. A unique identifier for this token request. A new jti should be allocated after the length of time for which the JWT would be considered valid based on the applicable "exp" value.
- scopes: is the requested scope(s), a space separated list of valid scopes defined in the Authentication Profile section below as specified in RFC 6749 section 3.3 and RFC 7521 section 4.1
- The JWT must be signed.
API User Access
This guide assumes you have been provided an API user in the PlanSource system. If you have not yet received your API user credentials, please reach out to your PlanSource point of contact for assistance.
2. Use the access token to access the Resource Server
The client makes a request to the endpoint using the token received from the Authorization Server as a Bearer token in the Authorization header (RFC 6750 section 2.1). We do not support the Form-Encoded Body Parameter or URI Query Parameter methods of using the Bearer token for utility/security reasons.
Authentication/Authorization errors
Type | Error | Description |
---|---|---|
Authorization Server / Resource Server | invalid_request | See RFC 6749 section 5.2 and See RFC 6750 section 3.1 |
Authorization Server | invalid_client | See RFC 6749 section 5.2 |
Authorization Server | invalid_grant | See RFC 6749 section 5.2 |
Authorization Server | unauthorized_client | See RFC 6749 section 5.2 |
Authorization Server | unsupported_grant_type | See RFC 6749 section 5.2 |
Authorization Server | invalid_scope | See RFC 6749 section 5.2 |
Authorization Server | invalid_scope | See RFC 6749 section 5.2 |
Resource Server | invalid_token | See RFC 6750 section 3.1 |
Resource Server | insufficient_scope | See RFC 6750 section 3.1 |
Authentication Profiles
Oauth Signed Assertions
Attribute Definitions
Field | Description |
---|---|
User Key (client_secret): | The client_secret. Used directly in authentication/authorization decisions. Required. Provided by PlanSource |
Lookup Code (client_id): | The client_id. A unique public identifier used to look up the API user. Required. Provided by PlanSource |
Authentication Types: | Currently hard coded to "all". We currently support "client_secret_jwt" (RFC 7523). Soon will also have "client_secret_saml" (RFC 7522) |
Scopes: | admin_api_v2 self_service_api_v1 all |
Sample Assertion
This is a pre-request script in Postman that is written in JavaScript. This sample stores the client secret, client lookup code, host URL, and the variables for the JWT. The JWT is then built and sent as the client_assertion to the access token endpoint.
var audience = "https://partner-dev-api.plansource.com/";
var secret = "PlanSourceProvidedClientSecret/UserKey";
var header = {
"alg": "HS256",
"typ": "JWT"
};
var stringifiedHeader = CryptoJS.enc.Utf8.parse(JSON.stringify(header));
var encodedHeader = CryptoJS.enc.Base64.stringify(stringifiedHeader);
var data = {
"iss":"dont care",
"sub": "PlanSourceProvidedClientLookupCode",
"aud": audience,
"scopes": "admin_api_v2",
"exp": (new Date() / 1000) + 3,
"logged_in_user": "PlanSourceProvidedClientAdministratorUserName",
};
var stringifiedData = CryptoJS.enc.Utf8.parse(JSON.stringify(data));
var encodedData = CryptoJS.enc.Base64.stringify(stringifiedData);
var token = encodedHeader + "." + encodedData;
var signature = CryptoJS.HmacSHA256(token, secret);
signature = CryptoJS.enc.Base64.stringify(signature);
var signedToken = token + "." + signature;
postman.setEnvironmentVariable("signedToken", signedToken);
Updated over 5 years ago