001package com.nimbusds.oauth2.sdk; 002 003 004import java.util.LinkedHashMap; 005import java.util.Map; 006 007import net.jcip.annotations.Immutable; 008 009import com.nimbusds.jwt.JWT; 010import com.nimbusds.jwt.JWTParser; 011 012/** 013 * JWT bearer grant. Used in access token requests with a JSON Web Token (JWT), 014 * such an OpenID Connect ID token. 015 * 016 * <p>Related specifications: 017 * 018 * <ul> 019 * <li>JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and 020 * Authorization Grants (RFC 7523), section-2.1. 021 * <li>Assertion Framework for OAuth 2.0 Client Authentication and 022 * Authorization Grants (RFC 7521), section 4.1. 023 * </ul> 024 */ 025@Immutable 026public class JWTBearerGrant extends AssertionGrant { 027 028 029 /** 030 * The grant type. 031 */ 032 public static final GrantType GRANT_TYPE = GrantType.JWT_BEARER; 033 034 035 /** 036 * The JWT assertion. 037 */ 038 private final JWT assertion; 039 040 041 /** 042 * Creates a new JSON Web Token (JWT) bearer assertion grant. 043 * 044 * @param assertion The JSON Web Token (JWT) assertion. Must not be 045 * {@code null}. 046 */ 047 public JWTBearerGrant(final JWT assertion) { 048 049 super(GRANT_TYPE); 050 051 if (assertion == null) 052 throw new IllegalArgumentException("The JWT assertion must not be null"); 053 054 this.assertion = assertion; 055 } 056 057 058 /** 059 * Gets the JSON Web Token (JWT) bearer assertion. 060 * 061 * @return The JWT bearer assertion. 062 */ 063 public JWT getJWTAssertion() { 064 065 return assertion; 066 } 067 068 069 @Override 070 public String getAssertion() { 071 072 return assertion.serialize(); 073 } 074 075 076 @Override 077 public Map<String,String> toParameters() { 078 079 Map<String,String> params = new LinkedHashMap<>(); 080 params.put("grant_type", GRANT_TYPE.getValue()); 081 params.put("assertion", assertion.serialize()); 082 return params; 083 } 084 085 086 /** 087 * Parses a JWT bearer grant from the specified parameters. 088 * 089 * <p>Example: 090 * 091 * <pre> 092 * grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer 093 * &assertion=eyJhbGciOiJFUzI1NiJ9.eyJpc3Mi[...omitted for brevity...]. 094 * J9l-ZhwP[...omitted for brevity...] 095 * </pre> 096 * 097 * @param params The parameters. 098 * 099 * @return The JWT bearer grant. 100 * 101 * @throws ParseException If parsing failed. 102 */ 103 public static JWTBearerGrant parse(final Map<String,String> params) 104 throws ParseException { 105 106 // Parse grant type 107 String grantTypeString = params.get("grant_type"); 108 109 if (grantTypeString == null) 110 throw new ParseException("Missing \"grant_type\" parameter", OAuth2Error.INVALID_REQUEST); 111 112 if (! GrantType.parse(grantTypeString).equals(GRANT_TYPE)) 113 throw new ParseException("The \"grant_type\" must be " + GRANT_TYPE, OAuth2Error.UNSUPPORTED_GRANT_TYPE); 114 115 // Parse JWT assertion 116 String assertionString = params.get("assertion"); 117 118 if (assertionString == null || assertionString.trim().isEmpty()) 119 throw new ParseException("Missing or empty \"assertion\" parameter", OAuth2Error.INVALID_REQUEST); 120 121 JWT assertion; 122 123 try { 124 assertion = JWTParser.parse(assertionString); 125 } catch (java.text.ParseException e) { 126 throw new ParseException("The \"assertion\" is not a JWT: " + e.getMessage(), OAuth2Error.INVALID_REQUEST, e); 127 } 128 129 return new JWTBearerGrant(assertion); 130 } 131}