Skip to main content

Resource Server

Resource Server is a term used in OAuth 2.0 and OpenID Connect. It refers to a server-side component that provides (or controls access to) a REST API.

For a certain API call to succeed the request has to contain a valid Access Token, added as a Bearer token in the Authorization header.

Access tokens issued by Identity Cloud have a JWT format and contain various fields:

  • sub - the ID of the user, or the Client ID when the access token was obtained using Client Credentials.
  • scope - the requested scopes as a space-separated string.
  • iss - the Identity Cloud Issuer.
  • iat - issued at in ms.
  • nbf - not before in ms.
  • exp - expiration in ms.
  • client_id - ID of the application.
  • permissions - permissions of the user for this application.

Your resource server must validate received access tokens. There are 2 approaches:

Token Introspection

Your resource server has to send received access tokens to the Identity Cloud Token Introspection endpoint.

Token validation using JWK Set

Your resource server may validate received access tokens locally by checking their signature instead of doing Token Introspection.

First you have to retrieve information about the signer key from the Identity Cloud JWK Set endpoint.

Send a GET request to https://yourinstance.id.nevis.cloud/.well-known/jwks.json. The response is in JSON format and may look as follows 1:

{
"keys" : [ {
"alg" : "RS256",
"use" : "sig",
"kid" : "Signer_OIDC",
"n" : "ntsuk...",
"e" : "AQAB",
"kty" : "RSA"
} ]
}

From this response you have to extract the modulus n and the exponent e. You can now use both components to validate received access tokens.

Example Java code to check token signature:

import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
import java.util.Base64;

class TokenHelper {

private static boolean isValid(String modulus, String exponent, String accessToken) {

PublicKey publicKey = getPublicKey(modulus, exponent);
int i = accessToken.lastIndexOf(".");
String signedData = jwt.substring(0, i);
byte[] signature = Base64.getUrlDecoder().decode(jwt.substring(i + 1));
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
boolean isValid = sig.verify(signature);
}

private PublicKey getPublicKey(String modulus, String exponent)
throws NoSuchAlgorithmException, InvalidKeySpecException {


byte[] exponentB = Base64.getUrlDecoder().decode(exponent);
byte[] modulusB = Base64.getUrlDecoder().decode(modulus);
BigInteger bigExponent = new BigInteger(1, exponentB);
BigInteger bigModulus = new BigInteger(1, modulusB);
return KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(bigModulus, bigExponent));
}
}

Your resource server must also check the exp field to ensure that expired tokens are not accepted.

Validation of the iss is optional but recommended.

1 The modulus n has been truncated to improve readability.