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 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         * Creates a new resource owner password credentials grant.
046         *
047         * @param username The resource owner's username. Must not be
048         *                 {@code null}.
049         * @param password The resource owner's password. Must not be
050         *                 {@code null}.
051         */
052        public ResourceOwnerPasswordCredentialsGrant(final String username,
053                                                     final Secret password) {
054
055                super(GRANT_TYPE);
056
057                if (username == null)
058                        throw new IllegalArgumentException("The username must not be null");
059
060                this.username = username;
061
062                if (password == null)
063                        throw new IllegalArgumentException("The password must not be null");
064
065                this.password = password;
066        }
067
068
069        /**
070         * Gets the resource owner's username.
071         *
072         * @return The username.
073         */
074        public String getUsername() {
075
076                return username;
077        }
078
079
080        /**
081         * Gets the resource owner's password.
082         *
083         * @return The password.
084         */
085        public Secret getPassword() {
086
087                return password;
088        }
089
090
091        @Override
092        public Map<String,String> toParameters() {
093
094                Map<String,String> params = new LinkedHashMap<>();
095                params.put("grant_type", GRANT_TYPE.getValue());
096                params.put("username", username);
097                params.put("password", password.getValue());
098                return params;
099        }
100
101
102        @Override
103        public boolean equals(Object o) {
104                if (this == o) return true;
105                if (o == null || getClass() != o.getClass()) return false;
106                ResourceOwnerPasswordCredentialsGrant that = (ResourceOwnerPasswordCredentialsGrant) o;
107                if (!username.equals(that.username)) return false;
108                return password.equals(that.password);
109        }
110
111
112        @Override
113        public int hashCode() {
114                int result = username.hashCode();
115                result = 31 * result + password.hashCode();
116                return result;
117        }
118
119
120        /**
121         * Parses a resource owner password credentials grant from the
122         * specified parameters.
123         *
124         * <p>Example:
125         *
126         * <pre>
127         * grant_type=password
128         * username=johndoe
129         * password=A3ddj3w
130         * </pre>
131         *
132         * @param params The parameters.
133         *
134         * @return The resource owner password credentials grant.
135         *
136         * @throws ParseException If parsing failed.
137         */
138        public static ResourceOwnerPasswordCredentialsGrant parse(final Map<String,String> params)
139                throws ParseException {
140
141                // Parse grant type
142                String grantTypeString = params.get("grant_type");
143
144                if (grantTypeString == null)
145                        throw new ParseException("Missing \"grant_type\" parameter", OAuth2Error.INVALID_REQUEST);
146
147                if (! GrantType.parse(grantTypeString).equals(GRANT_TYPE))
148                        throw new ParseException("The \"grant_type\" must be " + GRANT_TYPE, OAuth2Error.UNSUPPORTED_GRANT_TYPE);
149
150                // Parse the username
151                String username = params.get("username");
152
153                if (username == null || username.trim().isEmpty())
154                        throw new ParseException("Missing or empty \"username\" parameter", OAuth2Error.INVALID_REQUEST);
155
156                // Parse the password
157                String passwordString = params.get("password");
158
159                if (passwordString == null || passwordString.trim().isEmpty())
160                        throw new ParseException("Missing or empty \"password\" parameter", OAuth2Error.INVALID_REQUEST);
161
162                Secret password = new Secret(passwordString);
163
164                return new ResourceOwnerPasswordCredentialsGrant(username, password);
165        }
166}