Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fnymmm/authorization code flow frontend #75

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
12 changes: 12 additions & 0 deletions src/Server/src/Abstractions/Model/Session.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace IdOps;

public class Session
{
public string Id { get; set; }
public string ClientId { get; set; }
public string SecretId { get; set; }
public string CodeVerifier { get; set; }
public string SignalrConnectionId { get; set; }

public string RedirectUrl { get; set; }
}
8 changes: 8 additions & 0 deletions src/Server/src/Abstractions/Store/ISessionStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace IdOps.Store;

public interface ISessionStore
{
Session GetSession(string key);

void SaveSession(string key, Session session);
}
2 changes: 2 additions & 0 deletions src/Server/src/Api.Host/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
endpoints.MapGraphQL();
endpoints.MapControllers();
endpoints.MapHub<OpsHub>("/signal");
endpoints.MapHub<AccessTokenHub>("/clients/hub");
endpoints.MapAuthorizeClient();
});

if (!env.IsDevelopment())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using IdentityModel.Client;
using IdOps.Models;

namespace IdOps.Abstractions
{
public interface IIdentityService
{
Task<RequestTokenResult> RequestTokenAsync(
TokenRequestData request,
TokenRequest request,
CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

public interface IResultFactory<TResult, in TInput>
{
Task<TResult> Create(TInput input, CancellationToken cancellationToken);
Task<TResult> CreateRequestAsync(TInput input, CancellationToken cancellationToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ Task<TokenResponse> RequestTokenAsync(
Task<TokenResponse> RequestClientCredentialsTokenAsync(
ClientCredentialsTokenRequest request,
CancellationToken cancellationToken);

Task<TokenResponse> RequestAuthorizationCodeTokenAsync(
AuthorizationCodeTokenRequest request,
CancellationToken cancellationToken);
}
60 changes: 8 additions & 52 deletions src/Server/src/AuthTokenGenerator/IdentityService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using IdentityModel.Client;
using IdOps.Abstractions;
using IdOps.Models;
Expand All @@ -20,17 +18,16 @@ public IdentityService(
}

public async Task<RequestTokenResult> RequestTokenAsync(
TokenRequestData request,
TokenRequest request,
CancellationToken cancellationToken)
{
DiscoveryDocumentResponse disco = await _tokenClient.GetDiscoveryDocumentAsync(
request.Authority,
cancellationToken);

TokenResponse response = request.GrantType switch
{
"client_credentials" => await RequestClientCredentialTokenAsync(request, disco,cancellationToken),
_ => await RequestOtherGrantTypeTokenAsync(request, disco, cancellationToken)
"client_credentials" => await _tokenClient.RequestClientCredentialsTokenAsync(
(ClientCredentialsTokenRequest)request, cancellationToken),
"authorization_code" => await _tokenClient.RequestAuthorizationCodeTokenAsync(
(AuthorizationCodeTokenRequest)request, cancellationToken),
_ => await _tokenClient.RequestTokenAsync(request, cancellationToken)
};

if (response.IsError)
Expand All @@ -46,7 +43,7 @@ public async Task<RequestTokenResult> RequestTokenAsync(

return result;
}

TokenModel? accessToken = _tokenAnalyzer.Analyze(response.AccessToken);
if (accessToken == null)
{
Expand All @@ -55,49 +52,8 @@ public async Task<RequestTokenResult> RequestTokenAsync(
ErrorMessage = "Access Token could not be analyzed"
};
}
return new RequestTokenResult(true)
{
AccessToken = accessToken
};
}

private async Task<TokenResponse> RequestClientCredentialTokenAsync(
TokenRequestData request,
DiscoveryDocumentResponse disco,
CancellationToken cancellationToken)
{
return await _tokenClient.RequestClientCredentialsTokenAsync(
new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = request.ClientId,
ClientSecret = request.Secret,
GrantType = request.GrantType,
Scope = request.Scopes.Any() ? string.Join(" ", request.Scopes) : null
}, cancellationToken);
}

private async Task<TokenResponse> RequestOtherGrantTypeTokenAsync(
TokenRequestData request,
DiscoveryDocumentResponse disco,
CancellationToken cancellationToken)
{
var pars = new Dictionary<string, string>();

if (request.Scopes is { } s && s.Any())
{
pars.Add("scope", string.Join(" ", request.Scopes));
}

return await _tokenClient.RequestTokenAsync(
new TokenRequest
{
Address = disco.TokenEndpoint,
ClientId = request.ClientId,
ClientSecret = request.Secret,
GrantType = request.GrantType,
Parameters = new Parameters(pars)
}, cancellationToken);
return new RequestTokenResult(true) { AccessToken = accessToken };
}
}
}
13 changes: 12 additions & 1 deletion src/Server/src/AuthTokenGenerator/Models/TokenClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,18 @@ public async Task<TokenResponse> RequestClientCredentialsTokenAsync(
CancellationToken cancellationToken)
{
using HttpClient httpClient = _httpClientFactory.CreateClient();
var response = await httpClient.RequestClientCredentialsTokenAsync(request, cancellationToken);
var response =
await httpClient.RequestClientCredentialsTokenAsync(request, cancellationToken);
return response;
}

public async Task<TokenResponse> RequestAuthorizationCodeTokenAsync(
AuthorizationCodeTokenRequest request,
CancellationToken cancellationToken)
{
using HttpClient httpClient = _httpClientFactory.CreateClient();
var response =
await httpClient.RequestAuthorizationCodeTokenAsync(request, cancellationToken);
return response;
}
}
11 changes: 0 additions & 11 deletions src/Server/src/AuthTokenGenerator/Models/TokenRequestData.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ private static void AddEncryptionProviders(
IConfiguration configuration)
{
services.AddAzureKeyVault(configuration);
services.AddEncryptionProvider<KeyVaultEncryptionProvider>(isDefault: false);
services.AddEncryptionProvider<NoEncryptionProvider>(isDefault: true);
services.AddEncryptionProvider<KeyVaultEncryptionProvider>(isDefault: true);
services.AddEncryptionProvider<NoEncryptionProvider>(isDefault: false);
}

private static void AddConsumers(this IBusRegistrationConfigurator busConfigurator)
Expand Down
24 changes: 17 additions & 7 deletions src/Server/src/GraphQL/Client/ClientMutations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
using System.Threading.Tasks;
using HotChocolate;
using HotChocolate.Types;
using IdentityModel.Client;
using IdOps.Abstractions;
using IdOps.Model;
using IdOps.Models;
using IdOps.Store;

namespace IdOps.GraphQL
{
Expand Down Expand Up @@ -64,18 +66,26 @@ public async Task<SaveClientPayload> RemoveClientSecretAsync(
[AuthorizeClientAuthoring(AccessMode.Write, includeTenantAuth: false)]
public async Task<RequestTokenPayload> RequestTokenAsync(
[Service] IIdentityService identityService,
[Service] IResultFactory<TokenRequestData, RequestTokenInput> requestResultFactory,
RequestTokenInput input,
[Service] IResultFactory<TokenRequest, RequestTokenInput> requestResultFactory,
RequestClientCredentialsTokenInput input,
CancellationToken cancellationToken)
{
var tokenRequestData =
await requestResultFactory.Create(input,cancellationToken);


TokenRequest tokenRequest =
await requestResultFactory.CreateRequestAsync(input,cancellationToken);

RequestTokenResult tokenResult =
await identityService.RequestTokenAsync(tokenRequestData, cancellationToken);
await identityService.RequestTokenAsync(tokenRequest, cancellationToken);

return new RequestTokenPayload(tokenResult);
}

[AuthorizeClientAuthoring(AccessMode.Write, includeTenantAuth: false)]
public async Task<string> SaveSessionAsync(
[Service] ISessionStore sessionStore,
Session session)
{
sessionStore.SaveSession(session.Id, session);
return session.Id;
}
}
}
6 changes: 6 additions & 0 deletions src/Server/src/GraphQL/Client/ClientSubscriptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace IdOps.GraphQL;

public class ClientSubscriptions
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace IdOps.GraphQL;

public class RequestAuthorizationCodeTokenInput : RequestTokenInput
{
public string Code { get; set; }
public string Verifier { get; set; }
public string RedirectUri { get; set; }

public RequestAuthorizationCodeTokenInput(
string authority,
string clientId,
string secretId,
string grantType,
string code,
string verifier,
string redirectUri)
{
Authority = authority;
ClientId = clientId;
SecretId = secretId;
GrantType = grantType;
Code = code;
Verifier = verifier;
RedirectUri = redirectUri;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;

namespace IdOps.GraphQL
{
public class RequestClientCredentialsTokenInput : RequestTokenInput
{

public bool SaveTokens { get; set; }

public RequestClientCredentialsTokenInput(
string authority,
string clientId,
string secretId,
string grantType,
bool saveTokens)
{
Authority = authority;
ClientId = clientId;
SecretId = secretId;
GrantType = grantType;
SaveTokens = saveTokens;
}
}
}
19 changes: 8 additions & 11 deletions src/Server/src/GraphQL/Client/RequestTokenInput.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using IdOps.Abstractions;
using IdOps.Models;
using System;

namespace IdOps.GraphQL
namespace IdOps.GraphQL;

public class RequestTokenInput
{
public record RequestTokenInput(
string Authority,
Guid ClientId,
Guid SecretId,
string grantType,
bool SaveTokens);
public string Authority { get; set; }
public string ClientId { get; set; }
public string SecretId { get; set; }
public string GrantType { get; set; }
}
72 changes: 0 additions & 72 deletions src/Server/src/GraphQL/Client/TokenRequestDataResultFactory.cs

This file was deleted.

Loading