-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AMQP websocket custom proxy authenticator
- Loading branch information
Showing
5 changed files
with
264 additions
and
24 deletions.
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76
src/main/java/com/microsoft/azure/proton/transport/proxy/ProxyAuthenticator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.microsoft.azure.proton.transport.proxy; | ||
|
||
import com.microsoft.azure.proton.transport.proxy.impl.ChallengeResponseAccessHelper; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* A contract to authenticate a proxy server to tunnel a websocket connection to an AMQP broker. | ||
*/ | ||
public interface ProxyAuthenticator { | ||
/** | ||
* Authenticate a proxy server to tunnel a websocket connection to an AMQP broker. | ||
* <p> | ||
* This method is called when the proxy server replies to the CONNECT with 407 (Proxy Authentication Required) | ||
* challenge. The proxy server's challenge response includes a 'Proxy-Authenticate' header indicating | ||
* the authentication scheme(s) that the proxy supports. The implementation of this method should | ||
* <ul> | ||
* <li>enumerate the schemes using {@link ChallengeResponse#getAuthenticationSchemes()}) and choose the most | ||
* secure scheme the client supports,</li> | ||
* <li>identify the credential for the chosen scheme, </li> | ||
* <li>compute and return authorization value.The RFC7325 defines authorization format as a value that starts | ||
* with the selected scheme, followed by a space and the base64 encoded credentials for the scheme.</li> | ||
* </ul> | ||
* The returned authorization value will be sent to the proxy server in 'Proxy-Authorization' header to complete | ||
* the authentication. | ||
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/407">407 Proxy Authentication Required</a> | ||
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Proxy-Authenticate">Proxy-Authenticate</a> | ||
* @see <a href="https://datatracker.ietf.org/doc/html/rfc7235#section-4.4">RFC7235</a> | ||
* | ||
* @param response the challenge response from the proxy server. | ||
* @return the authorization value to send to the proxy server using 'Proxy-Authorization' header. | ||
*/ | ||
String authenticate(ChallengeResponse response); | ||
|
||
/** | ||
* Represents the 407 challenge response from the proxy server. | ||
*/ | ||
final class ChallengeResponse { | ||
static { | ||
ChallengeResponseAccessHelper.setAccessor(ChallengeResponse::new); | ||
} | ||
private static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; | ||
private final Map<String, List<String>> headers; | ||
|
||
/** | ||
* Creates the ChallengeResponse. | ||
* | ||
* @param headers the response headers | ||
*/ | ||
ChallengeResponse(Map<String, List<String>> headers) { | ||
this.headers = headers; | ||
} | ||
|
||
/** | ||
* Gets the headers. | ||
* | ||
* @return the headers. | ||
*/ | ||
public Map<String, List<String>> getHeaders() { | ||
return headers; | ||
} | ||
|
||
/** | ||
* Gets the authentication schemes supported by the proxy server. | ||
* | ||
* @return the authentication schemes supported by the proxy server. | ||
*/ | ||
public List<String> getAuthenticationSchemes() { | ||
return headers.get(PROXY_AUTHENTICATE); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
...n/java/com/microsoft/azure/proton/transport/proxy/impl/ChallengeResponseAccessHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.microsoft.azure.proton.transport.proxy.impl; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import com.microsoft.azure.proton.transport.proxy.ProxyAuthenticator; | ||
|
||
/** | ||
* The accessor helper for {@link ProxyAuthenticator.ChallengeResponse}. | ||
*/ | ||
public final class ChallengeResponseAccessHelper { | ||
private static ChallengeResponseAccessor accessor; | ||
|
||
/** | ||
* The accessor interface for {@link ProxyAuthenticator.ChallengeResponse} construction. | ||
*/ | ||
public interface ChallengeResponseAccessor { | ||
/** | ||
* Create an instance of {@link ProxyAuthenticator.ChallengeResponse} with the provided headers. | ||
* | ||
* @param headers the headers. | ||
* @return the created instance of {@link ProxyAuthenticator.ChallengeResponse}. | ||
*/ | ||
ProxyAuthenticator.ChallengeResponse internalCreate(Map<String, List<String>> headers); | ||
} | ||
|
||
/** | ||
* Sets the accessor. | ||
* | ||
* @param accessor the accessor. | ||
*/ | ||
public static void setAccessor(ChallengeResponseAccessor accessor) { | ||
ChallengeResponseAccessHelper.accessor = accessor; | ||
} | ||
|
||
/** | ||
* Creates an instance of {@link ProxyAuthenticator.ChallengeResponse} with the provided headers. | ||
* | ||
* @param headers the headers. | ||
* @return the created instance of {@link ProxyAuthenticator.ChallengeResponse}. | ||
*/ | ||
public static ProxyAuthenticator.ChallengeResponse internalCreate(Map<String, List<String>> headers) { | ||
if (accessor == null) { | ||
try { | ||
Class.forName(ProxyAuthenticator.ChallengeResponse.class.getName(), true, | ||
ChallengeResponseAccessHelper.class.getClassLoader()); | ||
} catch (ClassNotFoundException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
assert accessor != null; | ||
return accessor.internalCreate(headers); | ||
} | ||
|
||
/** | ||
* Private constructor to prevent instantiation. | ||
*/ | ||
private ChallengeResponseAccessHelper() { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters