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