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}