001package com.nimbusds.oauth2.sdk;
002
003
004import java.util.LinkedHashMap;
005import java.util.Map;
006
007import net.jcip.annotations.Immutable;
008
009import com.nimbusds.oauth2.sdk.auth.Secret;
010
011
012/**
013 * Resource owner password credentials grant. Used in access token requests
014 * with the resource owner's username and password.
015 *
016 * <p>Related specifications:
017 *
018 * <ul>
019 *     <li>OAuth 2.0 (RFC 6749), section 4.3.2.
020 * </ul>
021 */
022@Immutable
023public class ResourceOwnerPasswordCredentialsGrant extends AuthorizationGrant {
024
025
026        /**
027         * The associated grant type.
028         */
029        public static final GrantType GRANT_TYPE = GrantType.PASSWORD;
030
031
032        /**
033         * The username.
034         */
035        private final String username;
036
037
038        /**
039         * The password.
040         */
041        private final Secret password;
042
043
044        /**
045         * The requested scope.
046         */
047        private final Scope scope;
048
049
050        /**
051         * Creates a new resource owner password credentials grant.
052         *
053         * @param username The resource owner's username. Must not be
054         *                 {@code null}.
055         * @param password The resource owner's password. Must not be
056         *                 {@code null}.
057         * @param scope    The requested scope, {@code null} if not
058         *                 specified.
059         */
060        public ResourceOwnerPasswordCredentialsGrant(final String username,
061                                                     final Secret password,
062                                                     final Scope scope) {
063
064                super(GRANT_TYPE);
065
066                if (username == null)
067                        throw new IllegalArgumentException("The username must not be null");
068
069                this.username = username;
070
071                if (password == null)
072                        throw new IllegalArgumentException("The password must not be null");
073
074                this.password = password;
075
076                this.scope = scope;
077        }
078
079
080        /**
081         * Gets the resource owner's username.
082         *
083         * @return The username.
084         */
085        public String getUsername() {
086
087                return username;
088        }
089
090
091        /**
092         * Gets the resource owner's password.
093         *
094         * @return The password.
095         */
096        public Secret getPassword() {
097
098                return password;
099        }
100
101
102        /**
103         * Gets the requested scope.
104         *
105         * @return The requested scope.
106         */
107        public Scope getScope() {
108
109                return scope;
110        }
111
112
113        @Override
114        public Map<String,String> toParameters() {
115
116                Map<String,String> params = new LinkedHashMap<String,String>();
117
118                params.put("grant_type", GRANT_TYPE.getValue());
119
120                params.put("username", username);
121                params.put("password", password.getValue());
122
123                if (scope != null)
124                        params.put("scope", scope.toString());
125
126                return params;
127        }
128
129
130        /**
131         * Parses a resource owner password credentials grant from the
132         * specified parameters.
133         *
134         * <p>Example:
135         *
136         * <pre>
137         * grant_type=password
138         * username=johndoe
139         * password=A3ddj3w
140         * </pre>
141         *
142         * @param params The parameters.
143         *
144         * @return The resource owner password credentials grant.
145         *
146         * @throws ParseException If parsing failed.
147         */
148        public static ResourceOwnerPasswordCredentialsGrant parse(final Map<String,String> params)
149                throws ParseException {
150
151                // Parse grant type
152                String grantTypeString = params.get("grant_type");
153
154                if (grantTypeString == null)
155                        throw new ParseException("Missing \"grant_type\" parameter", OAuth2Error.INVALID_REQUEST);
156
157                GrantType grantType = new GrantType(grantTypeString);
158
159                if (! grantType.equals(GRANT_TYPE))
160                        throw new ParseException("The \"grant_type\" must be " + GRANT_TYPE, OAuth2Error.INVALID_GRANT);
161
162                // Parse the username
163                String username = params.get("username");
164
165                if (username == null || username.trim().isEmpty())
166                        throw new ParseException("Missing or empty \"username\" parameter", OAuth2Error.INVALID_REQUEST);
167
168                // Parse the password
169                String passwordString = params.get("password");
170
171                if (passwordString == null || passwordString.trim().isEmpty())
172                        throw new ParseException("Missing or empty \"password\" parameter", OAuth2Error.INVALID_REQUEST);
173
174                Secret password = new Secret(passwordString);
175
176                // Parse optional scope
177                String scopeValue = params.get("scope");
178
179                Scope scope = null;
180
181                if (scopeValue != null)
182                        scope = Scope.parse(scopeValue);
183
184                return new ResourceOwnerPasswordCredentialsGrant(username, password, scope);
185        }
186}