add all
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
namespace Best.HTTP.Request.Authenticators
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IAuthenticator"/> implementation for Bearer Token authentication.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Bearer Token authentication is a method used to access protected resources on a server.
|
||||
/// It involves including a bearer token in the Authorization header of an HTTP request to prove the identity of the requester.
|
||||
/// </remarks>
|
||||
public class BearerTokenAuthenticator : IAuthenticator
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BearerTokenAuthenticator class with the specified Bearer Token.
|
||||
/// </summary>
|
||||
/// <param name="token">The Bearer Token to use for authentication.</param>
|
||||
public string Token { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the required Authorization header with the Bearer Token for the HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="request">The HTTP request for which the Authorization header should be added.</param>
|
||||
/// <remarks>
|
||||
/// When sending an HTTP request to a server that requires Bearer Token authentication,
|
||||
/// this method sets the Authorization header with the Bearer Token to prove the identity of the requester.
|
||||
/// This allows the requester to access protected resources on the server.
|
||||
/// </remarks>
|
||||
public BearerTokenAuthenticator(string token) => this.Token = token;
|
||||
|
||||
public void SetupRequest(HTTPRequest request)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(this.Token))
|
||||
request.SetHeader("Authorization", $"Bearer {this.Token}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the server response with a 401 (Unauthorized) status code and a WWW-Authenticate header.
|
||||
/// This authenticator does not handle challenges and always returns <c>false</c>.
|
||||
/// </summary>
|
||||
/// <param name="req">The HTTP request that received the 401 response.</param>
|
||||
/// <param name="resp">The HTTP response containing the 401 (Unauthorized) status.</param>
|
||||
/// <returns><c>false</c>, as this authenticator does not handle challenges.</returns>
|
||||
/// <remarks>
|
||||
/// Bearer Token authentication typically does not require handling challenges,
|
||||
/// as the Bearer Token is included directly in the Authorization header of the request.
|
||||
/// This method always returns <c>false</c>, as no additional challenge processing is needed.
|
||||
/// </remarks>
|
||||
public bool HandleChallange(HTTPRequest req, HTTPResponse resp) => false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d868e2c2c58ac641a6eb45359eee94b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Best.HTTP.Request.Authentication;
|
||||
using Best.HTTP.Shared;
|
||||
|
||||
namespace Best.HTTP.Request.Authenticators
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IAuthenticator"/> implementation for HTTP Basic or Digest authentication.
|
||||
/// </summary>
|
||||
public class CredentialAuthenticator : IAuthenticator
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Authentication.Credentials"/> associated with this authenticator.
|
||||
/// </summary>
|
||||
public Credentials Credentials { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the CrendetialAuthenticator class with the specified <see cref="Authentication.Credentials"/>.
|
||||
/// </summary>
|
||||
/// <param name="credentials">The <see cref="Authentication.Credentials"/> to use for authentication.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown if <paramref name="credentials"/> is null.</exception>
|
||||
public CredentialAuthenticator(Credentials credentials)
|
||||
{
|
||||
if (credentials == null)
|
||||
throw new ArgumentNullException(nameof(credentials));
|
||||
|
||||
this.Credentials = credentials;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the required headers for the HTTP request based on the provided credentials.
|
||||
/// </summary>
|
||||
/// <param name="request">The HTTP request for which headers should be added.</param>
|
||||
public void SetupRequest(HTTPRequest request)
|
||||
{
|
||||
HTTPManager.Logger.Information(nameof(CredentialAuthenticator), $"SetupRequest({request}, {Credentials?.Type})", request.Context);
|
||||
|
||||
if (Credentials == null)
|
||||
return;
|
||||
|
||||
switch (Credentials.Type)
|
||||
{
|
||||
case AuthenticationTypes.Basic:
|
||||
// With Basic authentication we don't want to wait for a challenge, we will send the hash with the first request
|
||||
request.SetHeader("Authorization", string.Concat("Basic ", Convert.ToBase64String(Encoding.UTF8.GetBytes(Credentials.UserName + ":" + Credentials.Password))));
|
||||
break;
|
||||
|
||||
case AuthenticationTypes.Unknown:
|
||||
case AuthenticationTypes.Digest:
|
||||
var digest = DigestStore.Get(request.CurrentUri);
|
||||
if (digest != null)
|
||||
{
|
||||
string authentication = digest.GenerateResponseHeader(Credentials, false, request.MethodType, request.CurrentUri);
|
||||
if (!string.IsNullOrEmpty(authentication))
|
||||
request.SetHeader("Authorization", authentication);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the server response with a 401 (Unauthorized) status code and a WWW-Authenticate header.
|
||||
/// The authenticator might determine the authentication method to use and initiate authentication if needed.
|
||||
/// </summary>
|
||||
/// <param name="req">The HTTP request that received the 401 response.</param>
|
||||
/// <param name="resp">The HTTP response containing the 401 (Unauthorized) status.</param>
|
||||
/// <returns><c>true</c> if the challenge is handled by the authenticator and the request can be resent with authentication; otherwise, <c>false</c>.</returns>
|
||||
public bool HandleChallange(HTTPRequest req, HTTPResponse resp)
|
||||
{
|
||||
var www_authenticate = resp.GetHeaderValues("www-authenticate");
|
||||
|
||||
HTTPManager.Logger.Information(nameof(CredentialAuthenticator), $"HandleChallange({req}, {resp}, \"{www_authenticate}\")", req.Context);
|
||||
|
||||
string authHeader = DigestStore.FindBest(www_authenticate);
|
||||
if (!string.IsNullOrEmpty(authHeader))
|
||||
{
|
||||
var digest = DigestStore.GetOrCreate(req.CurrentUri);
|
||||
digest.ParseChallange(authHeader);
|
||||
|
||||
if (this.Credentials != null && digest.IsUriProtected(req.CurrentUri) && (!req.HasHeader("Authorization") || digest.Stale))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69e23320fe6bb034896f36f5773b06ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace Best.HTTP.Request.Authenticators
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an interface for various authentication implementations used in HTTP requests.
|
||||
/// </summary>
|
||||
public interface IAuthenticator
|
||||
{
|
||||
/// <summary>
|
||||
/// Set required headers or content for the HTTP request. Called right before the request is sent out.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The SetupRequest method will be called every time the request is redirected or retried.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="request">The HTTP request to which headers or content will be added.</param>
|
||||
void SetupRequest(HTTPRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the server is sending a 401 (Unauthorized) response with an WWW-Authenticate header.
|
||||
/// The authenticator might find additional knowledge about the authentication requirements (like what auth method it should use).
|
||||
/// If the authenticator is confident it can successfully (re)authenticate the request it can return true and the request will be resent to the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// More details can be found here:
|
||||
/// <list type="bullet">
|
||||
/// <item><description><see href="https://www.rfc-editor.org/rfc/rfc9110.html#status.401">RFC-9110 - 401 Unauthorized</see></description></item>
|
||||
/// <item><description><see href="https://www.rfc-editor.org/rfc/rfc9110.html#name-www-authenticate">RFC-9110 - WWW-Authenticate header</see></description></item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <param name="req">The HTTP request that received the 401 response.</param>
|
||||
/// <param name="resp">The HTTP response containing the 401 (Unauthorized) status.</param>
|
||||
/// <returns><c>true</c> if the challange is handled by the authenticator and the request can be re-sent with authentication.</returns>
|
||||
bool HandleChallange(HTTPRequest req, HTTPResponse resp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07b45cc6303c94540abce76b1370370a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user