API Security
The Runtime and Management API do not allow anonymous access and are secured by an OAuth/JWT access token. PolicyServer provides a built-in token issuer with the Management UI host, but you can also configure your own external token issuer.
Requesting a Token
The Management UI host provides an OAuth 2 (RFC 6749) compliant token endpoint to request access tokens. You create a client ID and secret for Management API clients when you set up the configuration for the Management UI host. Your client application will use this shared client ID and secret to request access tokens for the Management API.
To request an access token, send a POST to the /connect/token endpoint:
POST /token HTTP/1.1
Host: policyserver.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&
client_id=<insert id here>&
client_secret=<insert secret here>
Note
Technically, this is using the so-called OAuth 2.0 Client Credentials Grant. Client ID and secret can be sent either via an authorization header or the POST body. For more information, see the OAuth 2.0 spec
The response will contain an access token and a lifetime:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"expires_in":3600,
}
Note
Tokens issued by the built-in issuer are protected by cryptographic keys that are persisted to the database in the SigningKeys table. These keys are protected using the Data Protection API. See Data Protection for guidlines on how to configure this correctly in a load balanced or multi-instance environment.
Using your own Token Service
If you already have an OAuth 2.0 authorization server, you can use this server to issue access tokens for the API endpoints instead. You need to specifiy the authority of the external token service and configure either a value for the expected audience or scope (or both):
"PolicyServer": {
"host": {
"identity": {
"externalTokenIssuer": {
"authority": "https://demo.identityserver.io"
// at least one of the two values is required
"runtimeApiAudience" : "policyserver",
"runtimeApiScope" : "policyserver.runtime",
// at least one of the two values is required
"managementApiAudience" : "policyserver",
"managementApiScope" : "policyserver.management"
}
}
}
}
Note
The authorization server must support a discovery endpoint.
Mapping external claims
PolicyServer expects certain claims from the external issuer, but not all token services use the same claim types.
The ClaimsMapping
section allows you to remap those claims. The following snippet shows the default values:
"PolicyServer": {
"host": {
"identity": {
"externalTokenIssuer": {
// see above
"claimMappings": {
// must only yield one result
"ClientIdClaimTypes": [ "client_id" ],
"SubClaimTypes": [ "sub" ],
"NameClaimTypes: [ "name" ],
// allows multiple results
"ScopeClaimTypes": [ "scope" ],
"RoleClaimTypes": [ "role" ]
}
}
}
}
}
Tokens with sub claim
If the access token contains a sub claim, we assume the token is user centric, and apply PolicyServer authorization rules. The call will be unauthorized if the user is not an authorized PolicyServer administrator.
If your token service happens to emit a sub claim even for machine to machine communication scenarios, you can use the claim claimMappings to map both client_id and sub to the same claim type. We will then remove the sub claim, if it has the same value as client_id.
You can control this behavior in configuration:
"PolicyServer": {
"host": {
"identity": {
"externalTokenIssuer": {
// see above
"RemoveSubjectIdForMachineClients": true
}
}
}
}
Using the Access Token
To use the access token, send it on the authorization header to the API:
GET /management/policies
Host: policyserver.example.com
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
...