-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fork OidcClient Internally... for now...
- Loading branch information
1 parent
11cd081
commit 20bbcb4
Showing
47 changed files
with
3,236 additions
and
26 deletions.
There are no files selected for viewing
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 |
---|---|---|
@@ -1,3 +0,0 @@ | ||
[submodule "external/IdentityModel.OidcClient"] | ||
path = external/IdentityModel.OidcClient | ||
url = [email protected]:drasticactions/IdentityModel.OidcClient.git | ||
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
Submodule IdentityModel.OidcClient
deleted from
ff0caf
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// <auto-generated/> | ||
#nullable enable | ||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | ||
|
||
using System.Linq; | ||
using System.Net.Http; | ||
|
||
namespace IdentityModel.OidcClient.DPoP; | ||
|
||
/// <summary> | ||
/// Extensions for HTTP request/response messages | ||
/// </summary> | ||
public static class DPoPExtensions | ||
{ | ||
/// <summary> | ||
/// Sets the DPoP nonce request header if nonce is not null. | ||
/// </summary> | ||
public static void SetDPoPProofToken(this HttpRequestMessage request, string? proofToken) | ||
{ | ||
// remove any old headers | ||
request.Headers.Remove(OidcConstants.HttpHeaders.DPoP); | ||
// set new header | ||
request.Headers.Add(OidcConstants.HttpHeaders.DPoP, proofToken); | ||
} | ||
|
||
/// <summary> | ||
/// Reads the DPoP nonce header from the response | ||
/// </summary> | ||
public static string? GetDPoPNonce(this HttpResponseMessage response) | ||
{ | ||
response.Headers.TryGetValues(OidcConstants.HttpHeaders.DPoPNonce, out var headers); | ||
return headers?.FirstOrDefault() ?? string.Empty; | ||
} | ||
|
||
///// <summary> | ||
///// Reads the WWW-Authenticate response header to determine if the respone is in error due to DPoP | ||
///// </summary> | ||
//public static bool IsDPoPError(this HttpResponseMessage response) | ||
//{ | ||
// if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized) | ||
// { | ||
// var header = response.Headers.WwwAuthenticate.Where(x => x.Scheme == OidcConstants.AuthenticationSchemes.AuthorizationHeaderDPoP).FirstOrDefault(); | ||
// if (header != null && header.Parameter != null) | ||
// { | ||
// // WWW-Authenticate: DPoP error="use_dpop_nonce" | ||
// var values = header.Parameter.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); | ||
// var error = values.Select(x => | ||
// { | ||
// var parts = x.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); | ||
// if (parts.Length == 2 && parts[0] == OidcConstants.TokenResponse.Error) | ||
// { | ||
// return parts[1].Trim('"'); | ||
// } | ||
// return null; | ||
// }).Where(x => x != null).FirstOrDefault(); | ||
|
||
// return error == OidcConstants.TokenErrors.UseDPoPNonce || error == OidcConstants.TokenErrors.InvalidDPoPProof; | ||
// } | ||
// } | ||
|
||
// return false; | ||
//} | ||
|
||
/// <summary> | ||
/// Returns the URL without any query params | ||
/// </summary> | ||
/// <param name="request"></param> | ||
/// <returns></returns> | ||
public static string GetDPoPUrl(this HttpRequestMessage request) | ||
{ | ||
return request.RequestUri!.Scheme + "://" + request.RequestUri!.Authority + request.RequestUri!.LocalPath; | ||
} | ||
} |
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,17 @@ | ||
// <auto-generated/> | ||
#nullable enable | ||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | ||
|
||
namespace IdentityModel.OidcClient.DPoP; | ||
|
||
/// <summary> | ||
/// Models a DPoP proof token | ||
/// </summary> | ||
public class DPoPProof | ||
{ | ||
/// <summary> | ||
/// The proof token | ||
/// </summary> | ||
public string ProofToken { get; set; } = default!; | ||
} |
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,30 @@ | ||
// <auto-generated/> | ||
#nullable enable | ||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | ||
|
||
|
||
using System.Text.Json.Serialization; | ||
|
||
namespace IdentityModel.OidcClient.DPoP; | ||
|
||
/// <summary> | ||
/// Internal class to aid serialization of DPoP proof token payloads. Giving | ||
/// each claim a property allows us to add this type to the source generated | ||
/// serialization | ||
/// </summary> | ||
internal class DPoPProofPayload | ||
{ | ||
[JsonPropertyName(JwtClaimTypes.JwtId)] | ||
public string JwtId { get; set; } = default!; | ||
[JsonPropertyName(JwtClaimTypes.DPoPHttpMethod)] | ||
public string DPoPHttpMethod { get; set; } = default!; | ||
[JsonPropertyName(JwtClaimTypes.DPoPHttpUrl)] | ||
public string DPoPHttpUrl { get; set; } = default!; | ||
[JsonPropertyName(JwtClaimTypes.IssuedAt)] | ||
public long IssuedAt { get; set; } | ||
[JsonPropertyName(JwtClaimTypes. DPoPAccessTokenHash)] | ||
public string? DPoPAccessTokenHash { get; set; } | ||
[JsonPropertyName(JwtClaimTypes. Nonce)] | ||
public string? Nonce { get; set; } | ||
} |
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,37 @@ | ||
// <auto-generated/> | ||
#nullable enable | ||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | ||
|
||
namespace IdentityModel.OidcClient.DPoP; | ||
|
||
/// <summary> | ||
/// Models the request information to create a DPoP proof token | ||
/// </summary> | ||
public class DPoPProofRequest | ||
{ | ||
/// <summary> | ||
/// The HTTP URL of the request | ||
/// </summary> | ||
public string Url { get; set; } = default!; | ||
|
||
/// <summary> | ||
/// The HTTP method of the request | ||
/// </summary> | ||
public string Method { get; set; } = default!; | ||
|
||
///// <summary> | ||
///// The string representation of the JSON web key to use for DPoP. | ||
///// </summary> | ||
//public string DPoPJsonWebKey { get; set; } = default!; | ||
|
||
/// <summary> | ||
/// The nonce value for the DPoP proof token. | ||
/// </summary> | ||
public string? DPoPNonce { get; set; } | ||
|
||
/// <summary> | ||
/// The access token | ||
/// </summary> | ||
public string? AccessToken { get; set; } | ||
} |
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,107 @@ | ||
// <auto-generated/> | ||
#nullable enable | ||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | ||
|
||
using FishyFlip; | ||
using Microsoft.IdentityModel.JsonWebTokens; | ||
using Microsoft.IdentityModel.Tokens; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using System.Text.Json; | ||
|
||
namespace IdentityModel.OidcClient.DPoP; | ||
|
||
/// <summary> | ||
/// Used to create DPoP proof tokens. | ||
/// </summary> | ||
public class DPoPProofTokenFactory | ||
{ | ||
private readonly JsonWebKey _jwk; | ||
|
||
/// <summary> | ||
/// Constructor | ||
/// </summary> | ||
public DPoPProofTokenFactory(string proofKey) | ||
{ | ||
_jwk = new JsonWebKey(proofKey); | ||
|
||
if (_jwk.Alg.IsNullOrEmpty()) | ||
{ | ||
throw new ArgumentException("alg must be set on proof key"); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Creates a DPoP proof token. | ||
/// </summary> | ||
public DPoPProof CreateProofToken(DPoPProofRequest request) | ||
{ | ||
var jsonWebKey = _jwk; | ||
|
||
// jwk: representing the public key chosen by the client, in JSON Web Key (JWK) [RFC7517] format, | ||
// as defined in Section 4.1.3 of [RFC7515]. MUST NOT contain a private key. | ||
Dictionary<string, object> jwk; | ||
if (string.Equals(jsonWebKey.Kty, JsonWebAlgorithmsKeyTypes.EllipticCurve)) | ||
{ | ||
jwk = new Dictionary<string, object> | ||
{ | ||
{ "kty", jsonWebKey.Kty }, | ||
{ "x", jsonWebKey.X }, | ||
{ "y", jsonWebKey.Y }, | ||
{ "crv", jsonWebKey.Crv } | ||
}; | ||
} | ||
else if (string.Equals(jsonWebKey.Kty, JsonWebAlgorithmsKeyTypes.RSA)) | ||
{ | ||
jwk = new Dictionary<string, object> | ||
{ | ||
{ "kty", jsonWebKey.Kty }, | ||
{ "e", jsonWebKey.E }, | ||
{ "n", jsonWebKey.N } | ||
}; | ||
} | ||
else | ||
{ | ||
throw new InvalidOperationException("invalid key type."); | ||
} | ||
|
||
var header = new Dictionary<string, object>() | ||
{ | ||
{ "typ", JwtClaimTypes.JwtTypes.DPoPProofToken }, | ||
{ JwtClaimTypes.JsonWebKey, jwk }, | ||
}; | ||
|
||
var payload = new DPoPProofPayload | ||
{ | ||
JwtId = CryptoRandom.CreateUniqueId(), | ||
DPoPHttpMethod = request.Method, | ||
DPoPHttpUrl = request.Url, | ||
IssuedAt = DateTimeOffset.UtcNow.ToUnixTimeSeconds() | ||
}; | ||
|
||
if (!string.IsNullOrWhiteSpace(request.AccessToken)) | ||
{ | ||
// ath: hash of the access token. The value MUST be the result of a base64url encoding | ||
// the SHA-256 hash of the ASCII encoding of the associated access token's value. | ||
using var sha256 = SHA256.Create(); | ||
var hash = sha256.ComputeHash(Encoding.ASCII.GetBytes(request.AccessToken)); | ||
var ath = Base64Url.Encode(hash); | ||
|
||
payload.DPoPAccessTokenHash = ath; | ||
} | ||
|
||
if (!string.IsNullOrEmpty(request.DPoPNonce)) | ||
{ | ||
payload.Nonce = request.DPoPNonce!; | ||
} | ||
|
||
var handler = new JsonWebTokenHandler() { SetDefaultTimesOnTokenCreation = false }; | ||
var key = new SigningCredentials(jsonWebKey, jsonWebKey.Alg); | ||
var proofToken = handler.CreateToken(JsonSerializer.Serialize(payload, SourceGenerationContext.Default.DPoPProofPayload), key, header); | ||
|
||
return new DPoPProof { ProofToken = proofToken! }; | ||
} | ||
} |
Oops, something went wrong.