Skip to content

Commit

Permalink
Adds support for CIBA
Browse files Browse the repository at this point in the history
  • Loading branch information
kailash-b committed Dec 9, 2024
1 parent 0e5ded5 commit a94765e
Show file tree
Hide file tree
Showing 9 changed files with 424 additions and 3 deletions.
54 changes: 54 additions & 0 deletions src/Auth0.AuthenticationApi/AuthenticationApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Auth0.AuthenticationApi.Models.Ciba;

namespace Auth0.AuthenticationApi
{
Expand Down Expand Up @@ -497,6 +498,59 @@ public Task<PushedAuthorizationRequestResponse> PushedAuthorizationRequestAsync(
);
}

/// <inheritdoc/>
public Task<ClientInitiatedBackchannelAuthorizationResponse> ClientInitiatedBackchannelAuthorization(ClientInitiatedBackchannelAuthorizationRequest request,
CancellationToken cancellationToken = default)
{
if (request == null)
throw new ArgumentNullException(nameof(request));

var body = new Dictionary<string, string> {
{ "client_id", request.ClientId },
{ "binding_message", request.BindingMessage },
{ "login_hint", request.LoginHint.ToString() }
};

body.AddIfNotEmpty("scope", request.Scope);
body.AddIfNotEmpty("audience", request.Audience);

body.AddAll(request.AdditionalProperties);

ApplyClientAuthentication(request, body, true);

return connection.SendAsync<ClientInitiatedBackchannelAuthorizationResponse>(
HttpMethod.Post,
BuildUri("/bc-authorize"),
body,
cancellationToken: cancellationToken
);
}

/// <inheritdoc/>
public async Task<ClientInitiatedBackchannelAuthorizationTokenResponse> GetTokenAsync(
ClientInitiatedBackchannelAuthorizationTokenRequest request,
CancellationToken cancellationToken = default)
{
if (request == null)
throw new ArgumentNullException(nameof(request));

var body = new Dictionary<string, string>
{
{"grant_type", "urn:openid:params:grant-type:ciba"},
{"auth_req_id", request.AuthRequestId},
{"client_id", request.ClientId}
};
ApplyClientAuthentication(request, body, true);
var response = await connection.SendAsync<ClientInitiatedBackchannelAuthorizationTokenResponse>(
HttpMethod.Post,
tokenUri,
body,
cancellationToken: cancellationToken
).ConfigureAwait(false);

return response;
}

/// <summary>
/// Disposes of any owned disposable resources such as a <see cref="IAuthenticationConnection"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,17 @@ private async Task<T> SendRequest<T>(HttpRequestMessage request, CancellationTok

var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

return typeof(T) == typeof(string)
? (T)(object)content
: JsonConvert.DeserializeObject<T>(content, jsonSerializerSettings);
return DeserializeContent<T>(content);
}
}

internal T DeserializeContent<T>(string content)
{
return typeof(T) == typeof(string)
? (T)(object)content
: JsonConvert.DeserializeObject<T>(content, jsonSerializerSettings);
}

private void ApplyHeaders(HttpRequestMessage request, IDictionary<string, string> headers)
{
if (headers == null) return;
Expand Down
23 changes: 23 additions & 0 deletions src/Auth0.AuthenticationApi/IAuthenticationApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Auth0.AuthenticationApi.Models.Ciba;

namespace Auth0.AuthenticationApi
{
Expand Down Expand Up @@ -180,5 +181,27 @@ public interface IAuthenticationApiClient : IDisposable
/// a <see cref="PushedAuthorizationRequestResponse" /> with the details of the response.</returns>
Task<PushedAuthorizationRequestResponse> PushedAuthorizationRequestAsync(PushedAuthorizationRequest request,
CancellationToken cancellationToken = default);

/// <summary>
/// Initiates a Client Initiated Backchannel Authorization flow.
/// </summary>
/// <param name="request"><see cref="ClientInitiatedBackchannelAuthorizationRequest"/></param>
/// <param name="cancellationToken"></param>
/// <returns><see cref="Task"/> representing the async operation containing
/// a <see cref="ClientInitiatedBackchannelAuthorizationResponse" /> with the details of the response.</returns>
Task<ClientInitiatedBackchannelAuthorizationResponse> ClientInitiatedBackchannelAuthorization(ClientInitiatedBackchannelAuthorizationRequest request,
CancellationToken cancellationToken = default);

/// <summary>
/// Requests an Access Token using the CIBA flow
/// </summary>
/// <param name="request"><see cref="ClientInitiatedBackchannelAuthorizationTokenRequest"/></param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
/// <returns><see cref="Task"/> representing the async operation containing
/// a <see cref="ClientInitiatedBackchannelAuthorizationTokenResponse" /> with the requested tokens.</returns>
/// <remarks>
/// This must be polled while the user is completing their part of the flow at an interval no more frequent than that returned by <see cref="StartDeviceFlowAsync" />.
/// </remarks>
Task<ClientInitiatedBackchannelAuthorizationTokenResponse> GetTokenAsync(ClientInitiatedBackchannelAuthorizationTokenRequest request, CancellationToken cancellationToken = default);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Collections.Generic;
using Microsoft.IdentityModel.Tokens;

namespace Auth0.AuthenticationApi.Models.Ciba
{
/// <summary>
/// Contains information required for initiating a CIBA authorization request.
/// </summary>
public class ClientInitiatedBackchannelAuthorizationRequest : IClientAuthentication
{
/// <inheritdoc cref="IClientAuthentication.ClientId"/>
public string ClientId { get; set; }

/// <inheritdoc cref="IClientAuthentication.ClientSecret"/>
public string ClientSecret { get; set; }

/// <inheritdoc cref="IClientAuthentication.ClientAssertionSecurityKey"/>
public SecurityKey ClientAssertionSecurityKey { get; set; }

/// <inheritdoc cref="IClientAuthentication.ClientAssertionSecurityKeyAlgorithm"/>
public string ClientAssertionSecurityKeyAlgorithm { get; set; }

/// <summary>
/// A human-readable string intended to be displayed on both the device calling /bc-authorize and
/// the user’s authentication device (e.g. phone) to ensure the user is approving the correct request.
/// For example: “ABC-123-XYZ”.
/// </summary>
public string BindingMessage { get; set; }

/// <inheritdoc cref="Ciba.LoginHint"/>
public LoginHint LoginHint { get; set; }

/// <summary>
/// A space-separated list of OIDC and custom API scopes.
/// </summary>
public string Scope { get; set; }

/// <summary>
/// If you require an access token for an API, pass the unique identifier of the target API you want to access here
/// </summary>
public string Audience { get; set; }

/// <summary>
/// Used to configure a custom expiry time for this request.
/// </summary>
public int? RequestExpiry { get; set; }

/// <summary>
/// Any additional properties to use.
/// </summary>
public IDictionary<string, string> AdditionalProperties { get; set; } = new Dictionary<string, string>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Newtonsoft.Json;

namespace Auth0.AuthenticationApi.Models.Ciba
{
/// <summary>
/// Contains information about the client initiated backchannel authorization (CIBA) response.
/// </summary>
public class ClientInitiatedBackchannelAuthorizationResponse
{
/// <summary>
/// Unique id of the authorization request. Can be used further to poll for /oauth/token.
/// </summary>
[JsonProperty("auth_req_id")]
public string AuthRequestId { get; set; }

/// <summary>
/// Tells you how many seconds we have until the authentication request expires.
/// </summary>
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }

/// <summary>
/// Tells how many seconds you must leave between poll requests.
/// </summary>
[JsonProperty("interval")]
public int Interval { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Collections.Generic;
using Microsoft.IdentityModel.Tokens;

namespace Auth0.AuthenticationApi.Models.Ciba
{
/// <summary>
/// Contains information required for request token using CIBA.
/// </summary>
public class ClientInitiatedBackchannelAuthorizationTokenRequest : IClientAuthentication
{
/// <inheritdoc cref="IClientAuthentication.ClientId"/>
public string ClientId { get; set; }

/// <inheritdoc cref="IClientAuthentication.ClientSecret"/>
public string ClientSecret { get; set; }

/// <inheritdoc cref="IClientAuthentication.ClientAssertionSecurityKey"/>
public SecurityKey ClientAssertionSecurityKey { get; set; }

/// <inheritdoc cref="IClientAuthentication.ClientAssertionSecurityKeyAlgorithm"/>
public string ClientAssertionSecurityKeyAlgorithm { get; set; }

/// <summary>
/// Unique identifier of the authorization request. This value will be returned from the call to /bc-authorize.
/// </summary>
public string AuthRequestId { get; set; }

/// <summary>
/// Any additional properties to use.
/// </summary>
public IDictionary<string, string> AdditionalProperties { get; set; } = new Dictionary<string, string>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Newtonsoft.Json;

namespace Auth0.AuthenticationApi.Models.Ciba
{
public class ClientInitiatedBackchannelAuthorizationTokenResponse : AccessTokenResponse
{
[JsonProperty("scope")]
public string Scope { get; set; }
}
}
24 changes: 24 additions & 0 deletions src/Auth0.AuthenticationApi/Models/Ciba/LoginHint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Newtonsoft.Json;

namespace Auth0.AuthenticationApi.Models.Ciba
{
/// <summary>
/// Contains information about the user to contact for authentication.
/// </summary>
public class LoginHint
{
[JsonProperty("format")]
public string Format { get; set; }

[JsonProperty("iss")]
public string Issuer { get; set; }

[JsonProperty("sub")]
public string Subject { get; set; }

public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
}
Loading

0 comments on commit a94765e

Please sign in to comment.