001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.oauth2.sdk;
019
020
021import java.util.LinkedHashMap;
022import java.util.Map;
023
024import com.nimbusds.jose.util.Base64URL;
025import net.jcip.annotations.Immutable;
026
027
028/**
029 * SAML 2.0 bearer grant. Used in access token requests with a SAML 2.0 bearer
030 * assertion.
031 *
032 * <p>Related specifications:
033 *
034 * <ul>
035 *     <li>Assertion Framework for OAuth 2.0 Client Authentication and
036 *         Authorization Grants (RFC 7521), section 4.1.
037 *     <li>SAML 2.0 Profile for OAuth 2.0 Client Authentication and
038 *         Authorization Grants (RFC 7522), section-2.1.
039 * </ul>
040 */
041@Immutable
042public class SAML2BearerGrant extends AssertionGrant {
043
044
045        /**
046         * The grant type.
047         */
048        public static final GrantType GRANT_TYPE = GrantType.SAML2_BEARER;
049
050
051        /**
052         * Cached {@code unsupported_grant_type} exception.
053         */
054        private static final ParseException UNSUPPORTED_GRANT_TYPE_EXCEPTION
055                        = new ParseException("The \"grant_type\" must be " + GRANT_TYPE, OAuth2Error.UNSUPPORTED_GRANT_TYPE);
056
057
058        /**
059         * The SAML 2.0 assertion.
060         */
061        private final Base64URL assertion;
062
063
064        /**
065         * Creates a new SAML 2.0 bearer assertion grant.
066         *
067         * @param assertion The SAML 2.0 bearer assertion. Must not be
068         *                  {@code null}.
069         */
070        public SAML2BearerGrant(final Base64URL assertion) {
071
072                super(GRANT_TYPE);
073
074                if (assertion == null)
075                        throw new IllegalArgumentException("The SAML 2.0 bearer assertion must not be null");
076
077                this.assertion = assertion;
078        }
079
080
081        /**
082         * Gets the SAML 2.0 bearer assertion.
083         *
084         * @return The SAML 2.0 bearer assertion.
085         */
086        public Base64URL getSAML2Assertion() {
087
088                return assertion;
089        }
090
091
092        @Override
093        public String getAssertion() {
094
095                return assertion.toString();
096        }
097
098
099        @Override
100        public Map<String,String> toParameters() {
101
102                Map<String,String> params = new LinkedHashMap<>();
103                params.put("grant_type", GRANT_TYPE.getValue());
104                params.put("assertion", assertion.toString());
105                return params;
106        }
107
108
109        @Override
110        public boolean equals(Object o) {
111                if (this == o) return true;
112                if (o == null || getClass() != o.getClass()) return false;
113
114                SAML2BearerGrant that = (SAML2BearerGrant) o;
115
116                return assertion.equals(that.assertion);
117
118        }
119
120
121        @Override
122        public int hashCode() {
123                return assertion.hashCode();
124        }
125
126
127        /**
128         * Parses a SAML 2.0 bearer grant from the specified parameters.
129         *
130         * <p>Example:
131         *
132         * <pre>
133         * grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2-
134         * bearer&assertion=PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU
135         * [...omitted for brevity...]aG5TdGF0ZW1lbnQ-PC9Bc3NlcnRpb24-
136         * </pre>
137         *
138         * @param params The parameters.
139         *
140         * @return The SAML 2.0 bearer grant.
141         *
142         * @throws ParseException If parsing failed.
143         */
144        public static SAML2BearerGrant parse(final Map<String,String> params)
145                throws ParseException {
146
147                // Parse grant type
148                String grantTypeString = params.get("grant_type");
149
150                if (grantTypeString == null)
151                        throw MISSING_GRANT_TYPE_PARAM_EXCEPTION;
152
153                if (! GrantType.parse(grantTypeString).equals(GRANT_TYPE))
154                        throw UNSUPPORTED_GRANT_TYPE_EXCEPTION;
155
156                // Parse JWT assertion
157                String assertionString = params.get("assertion");
158
159                if (assertionString == null || assertionString.trim().isEmpty())
160                        throw MISSING_ASSERTION_PARAM_EXCEPTION;
161
162                return new SAML2BearerGrant(new Base64URL(assertionString));
163        }
164}