com.nimbusds.openid.connect.provider.spi.tokens.BaseSelfContainedAccessTokenClaimsCodec Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of c2id-server-sdk Show documentation
Show all versions of c2id-server-sdk Show documentation
SDK for Connect2id Server extensions, such as OpenID Connect claims
sources and OAuth 2.0 grant handlers
package com.nimbusds.openid.connect.provider.spi.tokens;
import java.util.*;
import net.jcip.annotations.ThreadSafe;
import net.minidev.json.JSONObject;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.oauth2.sdk.auth.X509CertificateConfirmation;
import com.nimbusds.oauth2.sdk.dpop.JWKThumbprintConfirmation;
import com.nimbusds.oauth2.sdk.id.*;
/**
* Base implementation of the SPI for encoding and decoding authorisations for
* self-contained access tokens into JWT claims sets.
*
* Provides encoding and decoding for all token parameters for which there
* is an appropriate standard JWT claim (see JSON Web Token (JWT) (RFC 7519),
* section 4.1, OAuth 2.0 Mutual-TLS Client Authentication and
* Certificate-Bound Access Tokens (RFC 8705), section 3.1), and OAuth 2.0
* Demonstrating Proof-of-Possession at the Application Layer (DPoP)
* (draft-ietf-oauth-dpop-16), section 6:
*
*
* - {@link AccessTokenAuthorization#getSubject subject} - "sub"
*
- {@link AccessTokenAuthorization#getActor actor} - "act"
*
- {@link AccessTokenAuthorization#getExpirationTime expiration time} - "exp"
*
- {@link AccessTokenAuthorization#getIssueTime issue time} - "iat"
*
- {@link AccessTokenAuthorization#getIssuer issuer} - "iss"
*
- {@link AccessTokenAuthorization#getAudienceList audience} - "aud"
*
- {@link AccessTokenAuthorization#getJWTID JWT ID} - "jti"
*
- {@link AccessTokenAuthorization#getClientCertificateConfirmation client X.509 certificate SHA-256 thumbprint (mTLS)} - "cnf.x5t#S256"
*
- {@link AccessTokenAuthorization#getJWKThumbprintConfirmation JWK SHA-256 thumbprint confirmation (DPoP)} - "cnf.jkt"
*
*
* The extending class should implement encoding and decoding for the
* remaining token parameters:
*
*
* - {@link AccessTokenAuthorization#getClientID client ID}
*
- {@link AccessTokenAuthorization#getSubjectType subject type}
*
- {@link AccessTokenAuthorization#getSubjectSessionKey subject session key}
*
- {@link AccessTokenAuthorization#getScope scope}
*
- {@link AccessTokenAuthorization#getClaimNames consented OpenID claim names}
*
- {@link AccessTokenAuthorization#getClaimsLocales preferred claims locales}
*
- {@link AccessTokenAuthorization#getPresetClaims preset OpenID claims}
*
- {@link AccessTokenAuthorization#getClaimsData claims fulfillment data}
*
- {@link AccessTokenAuthorization#getData additional data}
*
- {@link AccessTokenAuthorization#getOtherTopLevelParameters other top-level parameters}
*
*/
@ThreadSafe
public abstract class BaseSelfContainedAccessTokenClaimsCodec implements SelfContainedAccessTokenClaimsCodec {
/**
* The supported claim names.
*/
public static final Set SUPPORTED_CLAIM_NAMES = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList(
"sub", "act", "exp", "iat", "iss", "aud", "jti", "cnf"
))
);
@Override
public JWTClaimsSet encode(final AccessTokenAuthorization tokenAuthz, final TokenEncoderContext context) {
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
if (tokenAuthz.getSubject() != null) builder.subject(tokenAuthz.getSubject().getValue());
if (tokenAuthz.getActor() != null) builder.claim("act", tokenAuthz.getActor().toJSONObject());
if (tokenAuthz.getExpirationTime() != null) builder.expirationTime(Date.from(tokenAuthz.getExpirationTime()));
if (tokenAuthz.getIssueTime() != null) builder.issueTime(Date.from(tokenAuthz.getIssueTime()));
if (tokenAuthz.getIssuer() != null) builder.issuer(tokenAuthz.getIssuer().getValue());
if (tokenAuthz.getAudienceList() != null) builder.audience(Audience.toStringList(tokenAuthz.getAudienceList()));
if (tokenAuthz.getJWTID() != null) builder.jwtID(tokenAuthz.getJWTID().getValue());
JSONObject cnfValue = new JSONObject();
if (tokenAuthz.getClientCertificateConfirmation() != null) {
cnfValue.putAll(tokenAuthz.getClientCertificateConfirmation().toJWTClaim().getValue());
}
if (tokenAuthz.getJWKThumbprintConfirmation() != null) {
cnfValue.putAll(tokenAuthz.getJWKThumbprintConfirmation().toJWTClaim().getValue());
}
if (! cnfValue.isEmpty()) {
builder.claim("cnf", cnfValue);
}
return builder.build();
}
@Override
public JWTDetails advancedEncode(final AccessTokenAuthorization tokenAuthz, final TokenEncoderContext context) {
return new JWTDetails() {
@Override
public JOSEObjectType getType() {
return null;
}
@Override
public JWTClaimsSet getJWTClaimsSet() {
return encode(tokenAuthz, context);
}
};
}
@Override
public AccessTokenAuthorization decode(final JWTClaimsSet claimsSet, final TokenCodecContext context)
throws TokenDecodeException {
MutableAccessTokenAuthorization authz = new MutableAccessTokenAuthorization();
String sub = claimsSet.getSubject();
if (sub != null) authz.withSubject(new Subject(sub));
try {
Map act = claimsSet.getJSONObjectClaim("act");
if (act != null) authz.withActor(Actor.parse(new JSONObject(act)));
} catch (Exception e) {
throw new TokenDecodeException("Couldn't parse actor: " + e.getMessage(), e);
}
Date exp = claimsSet.getExpirationTime();
if (exp != null) authz.withExpirationTime(exp.toInstant());
Date iat = claimsSet.getIssueTime();
if (iat != null) authz.withIssueTime(iat.toInstant());
String iss = claimsSet.getIssuer();
if (iss != null) authz.withIssuer(new Issuer(iss));
List aud = claimsSet.getAudience();
if (aud != null && ! aud.isEmpty()) authz.withAudienceList(Audience.create(aud));
String jti = claimsSet.getJWTID();
if (jti != null) authz.withJWTID(new JWTID(jti));
authz.withClientCertificateConfirmation(X509CertificateConfirmation.parse(claimsSet));
authz.withJWKThumbprintConfirmation(JWKThumbprintConfirmation.parse(claimsSet));
return authz;
}
@Override
public AccessTokenAuthorization advancedDecode(final JWTDetails jwtDetails, final TokenCodecContext context)
throws TokenDecodeException {
return decode(jwtDetails.getJWTClaimsSet(), context);
}
}