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        /**
093         * Parses a SAML 2.0 bearer grant from the specified parameters.
094         *
095         * <p>Example:
096         *
097         * <pre>
098         * grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2-
099         * bearer&assertion=PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU
100         * [...omitted for brevity...]aG5TdGF0ZW1lbnQ-PC9Bc3NlcnRpb24-
101         * </pre>
102         *
103         * @param params The parameters.
104         *
105         * @return The SAML 2.0 bearer grant.
106         *
107         * @throws ParseException If parsing failed.
108         */
109        public static SAML2BearerGrant parse(final Map<String,String> params)
110                throws ParseException {
111
112                // Parse grant type
113                String grantTypeString = params.get("grant_type");
114
115                if (grantTypeString == null)
116                        throw MISSING_GRANT_TYPE_PARAM_EXCEPTION;
117
118                if (! GrantType.parse(grantTypeString).equals(GRANT_TYPE))
119                        throw UNSUPPORTED_GRANT_TYPE_EXCEPTION;
120
121                // Parse JWT assertion
122                String assertionString = params.get("assertion");
123
124                if (assertionString == null || assertionString.trim().isEmpty())
125                        throw MISSING_ASSERTION_PARAM_EXCEPTION;
126
127                return new SAML2BearerGrant(new Base64URL(assertionString));
128        }
129}