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>SAML 2.0 Profile for OAuth 2.0 Client Authentication and
019 *     Authorization Grants (draft-ietf-oauth-saml2-bearer-21), section-2.1.
020 *     <li>Assertion Framework for OAuth 2.0 Client Authentication and
021 *         Authorization Grants (draft-ietf-oauth-assertions-16), section 4.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         * The SAML 2.0 assertion.
036         */
037        private final Base64URL assertion;
038
039
040        /**
041         * Creates a new SAML 2.0 bearer assertion grant.
042         *
043         * @param assertion The SAML 2.0 bearer assertion. Must not be
044         *                  {@code null}.
045         */
046        public SAML2BearerGrant(final Base64URL assertion) {
047
048                super(GRANT_TYPE);
049
050                if (assertion == null)
051                        throw new IllegalArgumentException("The SAML 2.0 bearer assertion must not be null");
052
053                this.assertion = assertion;
054        }
055
056
057        /**
058         * Gets the SAML 2.0 bearer assertion.
059         *
060         * @return The SAML 2.0 bearer assertion.
061         */
062        public Base64URL getSAML2Assertion() {
063
064                return assertion;
065        }
066
067
068        @Override
069        public String getAssertion() {
070
071                return assertion.toString();
072        }
073
074
075        @Override
076        public Map<String,String> toParameters() {
077
078                Map<String,String> params = new LinkedHashMap<>();
079                params.put("grant_type", GRANT_TYPE.getValue());
080                params.put("assertion", assertion.toString());
081                return params;
082        }
083
084
085        /**
086         * Parses a SAML 2.0 bearer grant from the specified parameters.
087         *
088         * <p>Example:
089         *
090         * <pre>
091         * grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2-
092         * bearer&assertion=PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU
093         * [...omitted for brevity...]aG5TdGF0ZW1lbnQ-PC9Bc3NlcnRpb24-
094         * </pre>
095         *
096         * @param params The parameters.
097         *
098         * @return The SAML 2.0 bearer grant.
099         *
100         * @throws ParseException If parsing failed.
101         */
102        public static SAML2BearerGrant parse(final Map<String,String> params)
103                throws ParseException {
104
105                // Parse grant type
106                String grantTypeString = params.get("grant_type");
107
108                if (grantTypeString == null)
109                        throw new ParseException("Missing \"grant_type\" parameter", OAuth2Error.INVALID_REQUEST);
110
111                if (! GrantType.parse(grantTypeString).equals(GRANT_TYPE))
112                        throw new ParseException("The \"grant_type\" must be " + GRANT_TYPE, OAuth2Error.UNSUPPORTED_GRANT_TYPE);
113
114                // Parse JWT assertion
115                String assertionString = params.get("assertion");
116
117                if (assertionString == null || assertionString.trim().isEmpty())
118                        throw new ParseException("Missing or empty \"assertion\" parameter", OAuth2Error.INVALID_REQUEST);
119
120                return new SAML2BearerGrant(new Base64URL(assertionString));
121        }
122}