001    package com.nimbusds.oauth2.sdk.auth;
002    
003    
004    import java.util.Map;
005    
006    import com.nimbusds.oauth2.sdk.ParseException;
007    import com.nimbusds.oauth2.sdk.SerializeException;
008    import com.nimbusds.oauth2.sdk.http.CommonContentTypes;
009    import com.nimbusds.oauth2.sdk.http.HTTPRequest;
010    import com.nimbusds.oauth2.sdk.util.URLUtils;
011    
012    
013    /**
014     * Base abstract class for client authentication at the Token endpoint.
015     *
016     * <p>Related specifications:
017     *
018     * <ul>
019     *     <li>OAuth 2.0 (RFC 6749), section 2.3.
020     * </ul>
021     *
022     * @author Vladimir Dzhuvinov
023     */
024    public abstract class ClientAuthentication {
025            
026            
027            /**
028             * The client authentication method.
029             */
030            private final ClientAuthenticationMethod method;
031            
032            
033            /**
034             * Creates a new abstract client authentication.
035             *
036             * @param method The client authentication method. Must not be 
037             *               {@code null}.
038             */
039            protected ClientAuthentication(final ClientAuthenticationMethod method) {
040            
041                    if (method == null)
042                            throw new IllegalArgumentException("The client authentication method must not be null");
043                    
044                    this.method = method;
045            }
046            
047            
048            /**
049             * Gets the client authentication method.
050             *
051             * @return The client authentication method.
052             */
053            public ClientAuthenticationMethod getMethod() {
054            
055                    return method;
056            }
057            
058            
059            /**
060             * Parses the specified HTTP request for a supported client 
061             * authentication (see {@link ClientAuthenticationMethod}). This method
062             * is intended to aid parsing of authenticated 
063             * {@link com.nimbusds.oauth2.sdk.TokenRequest}s.
064             *
065             * @param httpRequest The HTTP request to parse. Must not be 
066             *                    {@code null}.
067             *
068             * @return The client authentication method, {@code null} if none or 
069             *         the method is not supported.
070             *
071             * @throws ParseException If the inferred client authentication 
072             *                        couldn't be parsed.
073             */
074            public static ClientAuthentication parse(final HTTPRequest httpRequest)
075                    throws ParseException {
076            
077                    // Check for client secret basic
078                    if (httpRequest.getAuthorization() != null && 
079                        httpRequest.getAuthorization().startsWith("Basic"))
080    
081                            return ClientSecretBasic.parse(httpRequest);
082                    
083                    // The other methods require HTTP POST with URL-encoded params
084                    if (httpRequest.getMethod() != HTTPRequest.Method.POST &&
085                        ! httpRequest.getContentType().match(CommonContentTypes.APPLICATION_URLENCODED))
086                            return null;
087                    
088                    
089                    String query = httpRequest.getQuery();
090                    
091                    if (query == null)
092                            return null;
093                    
094                    Map<String,String> params = URLUtils.parseParameters(query);
095                    
096                    // We have client secret post
097                    if (params.containsKey("client_id") && params.containsKey("client_secret"))
098                            return ClientSecretPost.parse(httpRequest);
099                    
100                    // Do we have a signed JWT assertion?
101                    if (params.containsKey("client_assertion") && params.containsKey("client_assertion_type"))
102                            return JWTAuthentication.parse(httpRequest);
103                    else
104                            return null;
105            }
106            
107            
108            /**
109             * Applies the authentication to the specified HTTP request by setting 
110             * its Authorization header and/or POST entity-body parameters 
111             * (according to the implemented client authentication method).
112             *
113             * @param httpRequest The HTTP request. Must not be {@code null}.
114             *
115             * @throws SerializeException If the client authentication parameters
116             *                            couldn't be applied to the HTTP request.
117             */
118            public abstract void applyTo(final HTTPRequest httpRequest) 
119                    throws SerializeException;
120    }