Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ protected AbstractAuthentication(JWTValidator jwtValidator, TokenExtractor extra
/**
* Concrete method to validate Bearer token headers and JWT claims.
*/
protected DecodedJWT validateBearerToken(Map<String, String> headers, HttpRequestInfo httpRequestInfo) throws BaseAuthException {
AuthToken authToken = extractor.extractBearer(headers);
return jwtValidator.validateToken(authToken.getAccessToken(), headers, httpRequestInfo);
protected DecodedJWT validateBearerToken(HttpRequestInfo httpRequestInfo) throws BaseAuthException {
AuthToken authToken = extractor.extractBearer(httpRequestInfo.getHeaders());
return jwtValidator.validateToken(authToken.getAccessToken(), httpRequestInfo);
}

/**
* Concrete method to validate DPoP token headers, JWT claims, and proof.
*/
protected DecodedJWT validateDpopTokenAndProof(Map<String, String> headers, HttpRequestInfo requestInfo)
protected DecodedJWT validateDpopTokenAndProof(HttpRequestInfo requestInfo)
throws BaseAuthException {

AuthValidatorHelper.validateHttpMethodAndHttpUrl(requestInfo);

AuthToken authToken = extractor.extractDPoPProofAndDPoPToken(headers);
DecodedJWT decodedJwtToken = jwtValidator.validateToken(authToken.getAccessToken(), headers, requestInfo);
AuthToken authToken = extractor.extractDPoPProofAndDPoPToken(requestInfo.getHeaders());
DecodedJWT decodedJwtToken = jwtValidator.validateToken(authToken.getAccessToken(), requestInfo);

dpopProofValidator.validate(authToken.getProof(), decodedJwtToken, requestInfo);

Expand All @@ -52,9 +52,7 @@ protected DecodedJWT validateDpopTokenAndProof(Map<String, String> headers, Http
/**
* Main abstract method for each concrete strategy.
*/
public abstract AuthenticationContext authenticate(
Map<String, String> headers,
HttpRequestInfo requestInfo
public abstract AuthenticationContext authenticate(HttpRequestInfo requestInfo
) throws BaseAuthException;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,27 @@ public AllowedDPoPAuthentication(JWTValidator jwtValidator,

/**
* Authenticates the request when DPoP Mode is Allowed (Accepts both DPoP and Bearer tokens) .
* @param headers request headers
* @param requestInfo HTTP request info
* @return AuthenticationContext with JWT claims
* @throws BaseAuthException if validation fails
*/
@Override
public AuthenticationContext authenticate(Map<String, String> headers, HttpRequestInfo requestInfo)
public AuthenticationContext authenticate(HttpRequestInfo requestInfo)
throws BaseAuthException {

String scheme = "";

try{
Map<String, String> normalizedHeader = normalize(headers);

scheme = extractor.getScheme(normalizedHeader);
scheme = extractor.getScheme(requestInfo.getHeaders());

if (scheme.equalsIgnoreCase(AuthConstants.BEARER_SCHEME)) {
DecodedJWT jwtToken = validateBearerToken(normalizedHeader, requestInfo);
AuthValidatorHelper.validateNoDpopPresence(normalizedHeader, jwtToken);
DecodedJWT jwtToken = validateBearerToken(requestInfo);
AuthValidatorHelper.validateNoDpopPresence(requestInfo.getHeaders(), jwtToken);
return buildContext(jwtToken);
}

if (scheme.equalsIgnoreCase(AuthConstants.DPOP_SCHEME)) {
DecodedJWT decodedJWT = validateDpopTokenAndProof(normalizedHeader, requestInfo);
DecodedJWT decodedJWT = validateDpopTokenAndProof(requestInfo);
return buildContext(decodedJWT);
}

Expand Down
5 changes: 2 additions & 3 deletions auth0-api-java/src/main/java/com/auth0/AuthClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,11 @@ public static AuthClient from(AuthOptions options) {

/**
* Verifies the incoming request headers and HTTP request info.
* @param headers request headers
* @param requestInfo HTTP request info
* @return AuthenticationContext with JWT claims
* @throws BaseAuthException if verification fails
*/
public AuthenticationContext verifyRequest(Map<String, String> headers, HttpRequestInfo requestInfo) throws BaseAuthException {
return orchestrator.process(headers, requestInfo);
public AuthenticationContext verifyRequest(HttpRequestInfo requestInfo) throws BaseAuthException {
return orchestrator.process(requestInfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public AuthenticationOrchestrator(AbstractAuthentication authStrategy) {
this.authStrategy = authStrategy;
}

public AuthenticationContext process(Map<String, String> headers, HttpRequestInfo requestInfo)
public AuthenticationContext process(HttpRequestInfo requestInfo)
throws BaseAuthException {
return authStrategy.authenticate(headers, requestInfo);
return authStrategy.authenticate(requestInfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,17 @@ public DisabledDPoPAuthentication(JWTValidator jwtValidator, TokenExtractor extr

/**
* Authenticates the request when DPoP Mode is Disabled (Accepts only Bearer tokens) .
* @param headers request headers
* @param requestInfo HTTP request info
* @return AuthenticationContext with JWT claims
* @throws BaseAuthException if validation fails
*/
@Override
public AuthenticationContext authenticate(Map<String, String> headers, HttpRequestInfo requestInfo)
public AuthenticationContext authenticate(HttpRequestInfo requestInfo)
throws BaseAuthException {

Map<String, String> normalizedHeader = normalize(headers);
// Map<String, String> normalizedHeader = normalize(requestInfo.getHeaders());
try {
DecodedJWT jwt = validateBearerToken(normalizedHeader, requestInfo);
DecodedJWT jwt = validateBearerToken(requestInfo);

return buildContext(jwt);
} catch (BaseAuthException ex){
Expand Down
44 changes: 44 additions & 0 deletions auth0-api-java/src/main/java/com/auth0/DomainResolver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.auth0;

import com.auth0.models.RequestContext;

import java.util.List;

/**
* Functional interface for dynamically resolving allowed issuer domains
* based on the incoming request context.
* <p>
* Used in multi-custom-domain (MCD) scenarios where the set of valid issuers
* cannot be determined statically at configuration time. The resolver receives
* a {@link RequestContext} containing the request URL, headers, and the
* unverified token issuer, and returns the list of allowed issuer domains.
* </p>
*
* <pre>{@code
* AuthOptions options = new AuthOptions.Builder()
* .domainsResolver(context -> {
* String host = context.getHeaders().get("host");
* return lookupIssuersForHost(host);
* })
* .audience("https://api.example.com")
* .build();
* }</pre>
*
* @see RequestContext
* @see com.auth0.models.AuthOptions.Builder#domainsResolver(DomainResolver)
*/
@FunctionalInterface
public interface DomainResolver {

/**
* Resolves the list of allowed issuer domains for the given request context.
*
* @param context the request context containing URL, headers, and unverified
* token issuer
* @return a list of allowed issuer domain strings (e.g.,
* {@code ["https://tenant1.auth0.com/"]});
* may return {@code null} or an empty list if no domains can be
* resolved
*/
List<String> resolveDomains(RequestContext context);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,18 @@ public RequiredDPoPAuthentication(JWTValidator jwtValidator,

/**
* Authenticates the request when DPoP Mode is Allowed (Accepts only DPoP tokens) .
* @param headers request headers
* @param requestInfo HTTP request info
* @return AuthenticationContext with JWT claims
* @throws BaseAuthException if validation fails
*/
@Override
public AuthenticationContext authenticate(Map<String, String> headers, HttpRequestInfo requestInfo)
public AuthenticationContext authenticate(HttpRequestInfo requestInfo)
throws BaseAuthException {

Map<String, String> normalizedHeader = normalize(headers);
// Map<String, String> normalizedHeader = normalize(requestInfo.getHeaders());

try {
DecodedJWT decodedJWT = validateDpopTokenAndProof(normalizedHeader, requestInfo);
DecodedJWT decodedJWT = validateDpopTokenAndProof(requestInfo);
return buildContext(decodedJWT);
}
catch (BaseAuthException ex){
Expand Down
66 changes: 66 additions & 0 deletions auth0-api-java/src/main/java/com/auth0/cache/AuthCache.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.auth0.cache;

/**
* Cache abstraction for storing authentication-related data such as
* OIDC discovery metadata and JWKS providers.
* <p>
* The SDK ships with a default in-memory LRU implementation
* ({@link InMemoryAuthCache}). Developers can implement this interface
* to plug in distributed cache backends (e.g., Redis, Memcached) without
* breaking changes to the SDK's public API.
* </p>
*
* <h3>Unified cache with key prefixes</h3>
* <p>
* A single {@code AuthCache<Object>} instance can serve as a unified cache
* for both discovery metadata and JWKS providers by using key prefixes:
* </p>
* <ul>
* <li>{@code discovery:{issuerUrl}} — OIDC discovery metadata</li>
* <li>{@code jwks:{jwksUri}} — JwkProvider instances</li>
* </ul>
*
* <h3>Thread Safety</h3>
* <p>
* All implementations <b>must</b> be thread-safe.
* </p>
*
* @param <V> the type of cached values
*/
public interface AuthCache<V> {

/**
* Retrieves a value from the cache.
*
* @param key the cache key
* @return the cached value, or {@code null} if not present or expired
*/
V get(String key);

/**
* Stores a value in the cache with the cache's default TTL.
*
* @param key the cache key
* @param value the value to cache
*/
void put(String key, V value);

/**
* Removes a specific entry from the cache.
*
* @param key the cache key to remove
*/
void remove(String key);

/**
* Removes all entries from the cache.
*/
void clear();

/**
* Returns the number of entries currently in the cache.
*
* @return the cache size
*/
int size();
}
Loading