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