OAuth Server
Learn how to configure the Authorization Server in AuthN to manage access to your APIs
You can use AuthN's OAuth 2 Authorization Server (AS) to define and manage access to your online resources, such as services and APIs. During authorization flows, a client application requests an access token from the AS. Permissions associated with the access token can be expressed via its scope . The client application can then use the access token to authorize requests to your Resource Server (RS).
Token values can be either an opaque string or a signed JSON Web Token (JWT). You can choose the type of active tokens in your Pangea project in AuthN Session Settings within the General section in the Pangea User Console. The RS can introspect an opaque access token to verify its issuer, audience, scopes, expiration, and other details, or read it from the signed JWT before granting access to a protected resource.
To set up the OAuth Server, Enable AuthN and navigate to the OAuth Server settings page in the Pangea User Console.
Audience
You can specify the intended audience for the access tokens issued by the AS. A list of the audience values you defined will be included in the token introspection results.
For example, an access token audience may contain an identifier of the RS or an API. In this case, permissions associated with the access token only apply at the RS or API matching the audience value. If there is no match, it may indicate a misrouting issue or a malicious access attempt, and access should be denied.
To manage audience values, click the pencil button next to the Audience label. In the edit dialog, type in an audience identifier and click Add to add a new value. Click the x button next to an existing audience value to remove it. Click Save to apply your changes.
You can also update the name of your OAuth Server in this dialog.
Configuration Details
In the Configuration Details section, you can find reference to the OAuth Server endpoints and copy them by clicking the corresponding tiles:
- Authorization Endpoint - Use this endpoint to start the Authorization Code grant .
- Token Endpoint - Use this endpoint to exchange an authorization code during the Authorization Code grant or client credentials during the Client Credentials grant for an access token.
- Metadata Endpoint - Use this endpoint to obtain Authorization Server Metadata in JSON format.
Clients
If you plan to support granular access to your services and APIs, you might want to start by setting up custom scopes on the Scopes tab.
Click the Clients tab to display existing OAuth 2 client registrations. To register a new client app, click the + OAuth Client button on the right.
In the Create OAuth Client dialog, use the following inputs to provide details about your client:
- Name - Assign a recognizable name to your client as it will appear in the list of clients in the OAuth Server settings. You can update this name at any time.
- Grant Types - Select the grant types your client application will use. Currently, only the Client Credentials grant is supported, but the Authorization Code grant with OpenID Connect (OIDC) extension will become available soon.
- Client secret expires in - Specify the lifespan for the new client secret. After it expires, you must generate a new secret for your client application.
- Access token expires in - Specify the lifespan for access tokens issued by the AS to this client.
- Allowed Scopes - Place the cursor in the input, select a scope value, and add it using the + button. This will enable the OAuth Server to add the scope to the tokens it issues to the client application. You can manage available scope values on the Scopes screen.
- Default Scopes - The scope values you add to the client registration are automatically included in the default scope. This default scope is added to the access token when no specific scope is requested during the authorization flow. You can remove the default values by clicking the
x
button. - Click the Create client button.
- After registering the client, copy its secret from the Your OAuth Client Secret dialog by clicking on the Client Secret tile. Once you close the dialog, you will not be able to access the secret value again. However, you can add new secrets to the client later, with the option to copy them.
- Select a client record from the list to view and edit its Details. To access client-specific actions, click the triple-dot button in the client's row. This menu lets you delete the client registration or add a new client secret. You can also manage the client’s secrets on the Secrets tab.
Scopes
Custom scopes
In OAuth 2 authorization flows, the optional scope parameter requests specific permissions to be included in a token. On the Scopes tab, you can add, modify, and delete custom scope values that your resource server recognizes.
To add a custom scope value, click the + Scope button on the right. In the Create Scope dialog, provide the new scope value details in the following fields:
-
Name - Define the scope value. This value will be included in the
scope
parameter during the authorization flow, and if granted, added to the access token's scope. -
Display Name - Provide a recognizable name that will appear in the Display Name column in the scopes list.
-
Description - Explain what this scope value represents. For example, describe the permissions granted with this scope value.
-
Consent Required - Check this option to require explicit user approval for adding this scope value to the access token. This setting applies only to the Authorization Code grant.
Predefined scopes
-
openid
When supported by the AS, the
openid
scope value extends the Authorization Code grant to include OpenID Connect (OIDC) authentication. By adding this value to thescope
parameter, the client application requests the user's identity information in the form of an ID Token from the AS.Additional OIDC-defined scope values can be used to request specific claims (that is, user information fields) to be included in the ID Token.
The OIDC scope values are provided by default on the Scopes page.
The predefined scopes apply only to the Authorization Code grant.
To edit a scope value, click a row in the list, and the scope value details will be displayed on the right. You can update all scope value properties except for its name. Click Save to apply your changes.
In the Clients section on the scope value details screen, you can see which client applications can request this scope to be added to the access tokens issued by the AS.
To delete a custom scope, click the triple-dot menu in the selected scope's row.
Client credentials grant
Diagram
The OAuth Server supports the Client Credentials grant . Your client application can use this grant to exchange its client ID and secret for access tokens.
Request access token
-
Exchange the client credentials for an access token at the token endpoint.
Send your access token request to the OAuth Server domain, which you can find in the OAuth Server Configuration Details.
For example, save the domain into an environment variable. You will also need the client ID and its secret to authorize the request.
Set environment variablesexport PANGEA_AUTHN_OAUTH_SERVER_DOMAIN="pdn-pgcrrev76s3d3bpj6bfwzol4g4wv4jft.login.staging.aws.pangea.cloud"
export PANGEA_CLIENT_ID="psa_7phb65qiigumuv4rrahqk3gnahwvij7c"
export PANGEA_CLIENT_SECRET="pck_tv67r5kxkilq6slsvpryu4k5svpm7vpf"noteAlternatively, your application can GET it from the authorization server metadata:
GET: /.well-known/oauth-authorization-servercurl --location "https://$PANGEA_AUTHN_OAUTH_SERVER_DOMAIN/.well-known/oauth-authorization-server"
response{
"grant_types_supported": [
"client_credentials"
],
"introspection_endpoint": "https://pdn-bz2qkqu75erqiry7ubuy5b5t462tswyj.login.dev.aws.pangea.cloud/v1beta/oauth/token/introspect",
"scopes_supported": [
"openid",
"email",
"address",
"phone",
"profile",
"files:upload"
],
"token_endpoint": "https://pdn-bz2qkqu75erqiry7ubuy5b5t462tswyj.login.staging.aws.pangea.cloud/v1beta/oauth/token",
"token_endpoint_auth_methods_supported": [
"client_secret_basic"
],
...
}Authorize your request with the client credentials using the Basic authentication scheme . For example, on a Unix-like system, including macOS, you can use the
base64
utility:Create client credentials for the Authorization headerecho -n "$PANGEA_CLIENT_ID:$PANGEA_CLIENT_SECRET" | base64
Basic authentication valuecHNhXzdwaGI2NXFpaWd1bXV2NHJyYWhxazNnbmFod3ZpajdjOnBja190djY3cjVreGtpbHE2c2xzdnByeXU0azVzdnBtN3ZwZg==
Use the credential in your request to the token endpoint. Provide the following parameters:
grant_type
- Use "client_credentials" as the value.- (optional)
scope
- Add space-delimited values that your resource server can understand before making the authorization decision.
For example:
POST: /v1beta/oauth/tokencurl --location "https://$PANGEA_AUTHN_OAUTH_SERVER_DOMAIN/v1beta/oauth/token" \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic cHNhXzdwaGI2NXFpaWd1bXV2NHJyYWhxazNnbmFod3ZpajdjOnBja190djY3cjVreGtpbHE2c2xzdnByeXU0azVzdnBtN3ZwZg==' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=files:upload' -
The OAuth Server validates the client credentials.
-
The OAuth Server responds with an access token . In the response, you receive a token value, either opaque or a signed JWT. The token type is always "Bearer", and the token lifespan is expressed in seconds in the
expires_in
field.Depending on the Session Configuration option selected on the AuthN Session Settings page within the General section, the access token value could be an opaque string or a signed JWT:
/v1beta/oauth/token response: opaque (stateful) access token{
"access_token": "pts_hpbc3klkkq54tigu4osc5eygthxps6vf",
"token_type": "Bearer",
"expires_in": 86399
}/v1beta/oauth/token response: signed JWT (stateless) access token{
"access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6InB2aV91Zmw0cnlkcTNpdnZrZTU0dzNzb2twZXllaWxud2Q1eXwxIiwia3R5IjoiSldUIn0.eyJpc3MiOiJodHRwczovL3Bkbi1wZ2NycmV2NzZzM2QzYnBqNmJmd3pvbDRnNHd2NGpmdC5sb2dpbi5zdGFnaW5nLmF3cy5wYW5nZWEuY2xvdWQiLCJzdWIiOiJwc2FfYWV5dmJvbWR3Mmw1d3Zqb203d210MnRtZnNzN3BwcGsiLCJleHAiOjE3MjYwMjYxNzYsIm5iZiI6MTcyNTkzOTc3NiwiaWF0IjoxNzI1OTM5Nzc2LCJqdGkiOiJwbXRfeXN0cXB5eG42c3d5aGd1Zm9iZmFmanFxN2xhNXBkZWIiLCJ0b2tlbl90eXBlIjoiY2xpZW50X2FjY291bnQiLCJvd25lciI6Ik15IEFwcCIsInNjb3BlcyI6WyJmaWxlczp1cGxvYWQiXX0.KXoklx3F0QGdMAUgT8g-Pm5n_FwPaQPpqjs4_LMS17eqNZDYn3FzG3Q7rRMnqnZPbmDvdwbZFu31ErYMbXXLSQ",
"token_type": "Bearer",
"expires_in": 86399
} -
Your application authorizes a request to the resource server by adding the bearer token to the Authorization header.
For example:
curl --location 'https://api.example.com/resource' \
--header 'Authorization: Bearer pts_hpbc3klkkq54tigu4osc5eygthxps6vf' \
--header 'Content-Type: application/json' \
--data '{
"resource-id": "resource-1"
}'
Validate access token
Opaque access token
-
The resource server introspects the access token.
Authorize your request with the client ID using the Basic authentication scheme. For example, on macOS, you can use the
base64
utility:Create client credentials for the Authorization headerecho -n "$PANGEA_CLIENT_ID:" | base64
noteYou must add a colon after the client ID to indicate the separation between the username (client ID) and password, even though the latter is not required.
Basic authentication valuecHNhXzdwaGI2NXFpaWd1bXV2NHJyYWhxazNnbmFod3ZpajdjOg==
Provide the access token value as the
token
parameter:POST: /v1beta/oauth/token/introspectcurl --location "https://$PANGEA_AUTHN_OAUTH_SERVER_DOMAIN/v1beta/oauth/token/introspect" \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic cHNhXzdwaGI2NXFpaWd1bXV2NHJyYWhxazNnbmFod3ZpajdjOg==' \
--data-urlencode 'token=pts_hpbc3klkkq54tigu4osc5eygthxps6vf' -
The OAuth Server returns a standard Introspection Response :
response{
"client_id": "psa_aeyvbomdw2l5wvjom7wmt2tmfss7pppk",
"scope": "files:upload",
"aud": [
"api.example.com",
"api2.example.com"
],
"iss": "https://pdn-pgcrrev76s3d3bpj6bfwzol4g4wv4jft.login.staging.aws.pangea.cloud",
"exp": 1726025937,
"iat": 1725939537,
"nbf": 1725939537,
"jti": "pmt_ygi5fdri4rqlnhvr7hypwoima3age35p",
"token_type": "Bearer",
"active": true
}noteCurrently, only opaque access tokens issued by the AuthN OAuth Server can be introspected.
Signed JWT
-
The RS validates the stateless access token.
The decoded JWT payload contains similar data to introspection results:
Decoded JWT payload{
"iss": "https://pdn-pgcrrev76s3d3bpj6bfwzol4g4wv4jft.login.staging.aws.pangea.cloud",
"sub": "",
"exp": 1726026176,
"nbf": 1725939776,
"iat": 1725939776,
"jti": "pmt_ystqpyxn6swyhgufobfafjqq7la5pdeb",
"client_id": "psa_aeyvbomdw2l5wvjom7wmt2tmfss7pppk",
"token_type": "Bearer",
"active": true
}Verify JWT signature
To verify the signature of a JWT received by your application, your application can retrieve the public key from the JSON Web Key Set (JWKS) available at the issuer's /v1beta/oauth/jwks.json path. Pangea issues standard JWTs that can be validated with JWKS using your favorite library. This approach to validate JWTs is widely supported.
In protected environments, you could also retrieve the corresponding public key using Vault APIs.
Use JWKS
If your application, such as a mobile app, cannot safely store the Vault service token, you can instead use the publicly available JWKS to generate the public key. Append /v1beta/oauth/jwks.json path to the issuer URI in a decoded JWT and use it to retrieve the JWKS. For example:
jwks.json{
"keys" : [
...,
{
"alg" : "ES256",
"crv" : "P-256",
"kid" : "pvi_dzbpej6fegceveo66ofsjc6jq4nt5xwh|2",
"kty" : "EC",
"x" : "HNVhj_BFpDZWc5i-1TRR2dLmSgvzlLbKD6BUDsUKGeo",
"y" : "laA5au3cuwoy78dwzi7E2urphJpk8tUF0RBHaavdQe8"
},
{
"alg" : "ES256",
"crv" : "P-256",
"kid" : "pvi_dzbpej6fegceveo66ofsjc6jq4nt5xwh|1",
"kty" : "EC",
"x" : "kWqMYYDrxFLR0S88wxisf6ro7JaQwRZlDhSUiHPe9sc",
"y" : "MFxmc5OF4cRaQ0dDakw6pAG3xIINFeyzuYqWeQs19yk"
}
]
}New versions of keys will be added to the set as the JWT key saved in Vault is rotated. The key version is shown in the "kid" value after the
|
delimiter.To automate the JWKS retrieval and application you can use one of the JWT Libraries for Token Signing/Verification .
Example:
pip install 'pyjwt[crypto]'
Use JWKSimport jwt
from jwt import PyJWKClient
token = "eyJhbGciOiJFUzI1NiIsImtpZCI6InB2aV9qZGp5amFudnZtb3hpMnB1N3RtcWFnY3B4enV2bnViZXw1Iiwia3R5IjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
url = "<JWKS-path>"
jwks_client = PyJWKClient(url)
signing_key = jwks_client.get_signing_key_from_jwt(token)
data = jwt.decode(
token,
signing_key.key,
algorithms=["ES256"],
options={"verify_exp": False},
)
print(data)Use public key from Vault
To obtain the public key dynamically, you can request it from the Vault /v1/get endpoint by providing the JWT key ID and authorizing the request with a Vault service token. You can get the default service token for Vault from its Configuration Details under Vault Overview in the Pangea User Console, or you can create a service token in Project Settings >> Tokens and explicitly associate it with Vault.
export PANGEA_DOMAIN="aws.us.pangea.cloud"
export PANGEA_VAULT_TOKEN="pts_gqmqvvxk4yhirapuhw6bs7nswu"Note that the items in Vault can be versioned. Rotating the JWT signing key will require the use of an appropriate version of the public key in your application. In the request data, you can optionally provide the version number or request all versions of the public key via the "version" parameter. If you don't specify a version in your request, the latest will be returned.
/v1/get JWT public keycurl --location "https://vault.$PANGEA_DOMAIN/v1/get" \
--header "Authorization: Bearer $PANGEA_VAULT_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"id":"pvi_jdjyjanvvmoxi2pu7tmqagcpxzuvnube",
"version":"all"
}'The latest public key version for verifying the JWT signature will be included as
result.current_version.public
within the response. Older versions can be found in the "version" array. Including previous keys allows you to accept tokens minted just before the signing key has been rotated, either manually or on an automated schedule./v1/get response{
"result": {
"current_version": {
"public_key": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGY4p4VYSqOAh2yncQE31kJaWzgAr\n/fVvYAyf7hnkd6bhJmN24IiujCiYhKiRWA7QGwF7jmPvTDjxwd4/0RSt8Q==\n-----END PUBLIC KEY-----\n",
"state": "active",
"version": 1,
...
},
"id": "pvi_jdjyjanvvmoxi2pu7tmqagcpxzuvnube",
"item_state": "enabled",
"metadata": {
"authn_config_id": "pro_jbxwlzvhyubldhe27fa57t234k52jda3"
},
"purpose": "jwt",
"type": "asymmetric_key",
...
"versions": [
{
"public_key": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGY4p4VYSqOAh2yncQE31kJaWzgAr\n/fVvYAyf7hnkd6bhJmN24IiujCiYhKiRWA7QGwF7jmPvTDjxwd4/0RSt8Q==\n-----END PUBLIC KEY-----\n",
"state": "active",
"version": 5,
...
},
...,
{
"public_key": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo4Y3Vh3dU2EaiFrPAZ1LKVukdHz5\n7wKJmEOMB4x8TyvIEuC/w61yr3fdU23rBpyPguAx/IWnVI2UV8TAjZ7HVQ==\n-----END PUBLIC KEY-----\n",
"state": "deactivated",
"version": 1,
...
}
]
},
"status": "Success",
"summary": "Key pair retrieved",
...
}In the above example, the latest/current version is
5
.-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5kCKMlbs8eYSxV8JzGkpmy1CI9BO
AJHqsQ2ubRr1dQkVwH183NFs6/8khtMUTtCzmtZ7F/hjAVG7QUxkzt/kLA==
-----END PUBLIC KEY-----noteFor testing your JWT, for example on https://jwt.io/, you can get a public key from Vault Secrets & Keys in the Pangea User Console:
- Navigate to AuthN General >> Session Settings and click the Signing Key Vault ID link. This will take you to the JWT key saved in Vault.
- The JWT Key form for the selected Vault item should be opened on the right-hand side. If it is not, click on the row representing your JWT Key.
- In the JWT Key form, click the triple-dot menu button and select Copy public key.
- Save the key in a location accessible to your application.
Process claims, make authorization decision
-
Your resource server is likely to base its authorization decisions on the following fields in the introspection response:
- "active" - A value of
true
indicates that the token is valid and currently active. A value offalse
means the token is invalid, expired, revoked, or otherwise inactive. - "client_id" - Represents the client ID which initially requested the token.
- "scope" - Space-delimited scope values that are included in the token.
- "aud" - Represents the intended service(s) or API(s) for which this access token is issued.
- "iss" - The origin of the OAuth Server.
- "exp" - The token's expiration date.
- "iat" - The token's issue date.
- "nbf" - The token's effective date.
Each date is expressed as the number of seconds since the Unix Epoch (January 1, 1970, UTC).
- "active" - A value of
-
The resource server returns data from the API or responds with an error .
Was this article helpful?