001package com.nimbusds.oauth2.sdk; 002 003 004import java.util.LinkedHashMap; 005import java.util.Map; 006 007import com.nimbusds.jose.util.Base64URL; 008import net.jcip.annotations.Immutable; 009 010 011/** 012 * SAML 2.0 bearer grant. Used in access token requests with a SAML 2.0 bearer 013 * assertion. 014 * 015 * <p>Related specifications: 016 * 017 * <ul> 018 * <li>Assertion Framework for OAuth 2.0 Client Authentication and 019 * Authorization Grants (RFC 7521), section 4.1. 020 * <li>SAML 2.0 Profile for OAuth 2.0 Client Authentication and 021 * Authorization Grants (RFC 7522), section-2.1. 022 * </ul> 023 */ 024@Immutable 025public class SAML2BearerGrant extends AssertionGrant { 026 027 028 /** 029 * The grant type. 030 */ 031 public static final GrantType GRANT_TYPE = GrantType.SAML2_BEARER; 032 033 034 /** 035 * Cached {@code unsupported_grant_type} exception. 036 */ 037 private static final ParseException UNSUPPORTED_GRANT_TYPE_EXCEPTION 038 = new ParseException("The \"grant_type\" must be " + GRANT_TYPE, OAuth2Error.UNSUPPORTED_GRANT_TYPE); 039 040 041 /** 042 * The SAML 2.0 assertion. 043 */ 044 private final Base64URL assertion; 045 046 047 /** 048 * Creates a new SAML 2.0 bearer assertion grant. 049 * 050 * @param assertion The SAML 2.0 bearer assertion. Must not be 051 * {@code null}. 052 */ 053 public SAML2BearerGrant(final Base64URL assertion) { 054 055 super(GRANT_TYPE); 056 057 if (assertion == null) 058 throw new IllegalArgumentException("The SAML 2.0 bearer assertion must not be null"); 059 060 this.assertion = assertion; 061 } 062 063 064 /** 065 * Gets the SAML 2.0 bearer assertion. 066 * 067 * @return The SAML 2.0 bearer assertion. 068 */ 069 public Base64URL getSAML2Assertion() { 070 071 return assertion; 072 } 073 074 075 @Override 076 public String getAssertion() { 077 078 return assertion.toString(); 079 } 080 081 082 @Override 083 public Map<String,String> toParameters() { 084 085 Map<String,String> params = new LinkedHashMap<>(); 086 params.put("grant_type", GRANT_TYPE.getValue()); 087 params.put("assertion", assertion.toString()); 088 return params; 089 } 090 091 092 @Override 093 public boolean equals(Object o) { 094 if (this == o) return true; 095 if (o == null || getClass() != o.getClass()) return false; 096 097 SAML2BearerGrant that = (SAML2BearerGrant) o; 098 099 return assertion.equals(that.assertion); 100 101 } 102 103 104 @Override 105 public int hashCode() { 106 return assertion.hashCode(); 107 } 108 109 110 /** 111 * Parses a SAML 2.0 bearer grant from the specified parameters. 112 * 113 * <p>Example: 114 * 115 * <pre> 116 * grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2- 117 * bearer&assertion=PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU 118 * [...omitted for brevity...]aG5TdGF0ZW1lbnQ-PC9Bc3NlcnRpb24- 119 * </pre> 120 * 121 * @param params The parameters. 122 * 123 * @return The SAML 2.0 bearer grant. 124 * 125 * @throws ParseException If parsing failed. 126 */ 127 public static SAML2BearerGrant parse(final Map<String,String> params) 128 throws ParseException { 129 130 // Parse grant type 131 String grantTypeString = params.get("grant_type"); 132 133 if (grantTypeString == null) 134 throw MISSING_GRANT_TYPE_PARAM_EXCEPTION; 135 136 if (! GrantType.parse(grantTypeString).equals(GRANT_TYPE)) 137 throw UNSUPPORTED_GRANT_TYPE_EXCEPTION; 138 139 // Parse JWT assertion 140 String assertionString = params.get("assertion"); 141 142 if (assertionString == null || assertionString.trim().isEmpty()) 143 throw MISSING_ASSERTION_PARAM_EXCEPTION; 144 145 return new SAML2BearerGrant(new Base64URL(assertionString)); 146 } 147}