diff --git a/TodoApi/Users/AccessTokenResponse.cs b/TodoApi/Users/AccessTokenResponse.cs new file mode 100644 index 00000000..7c7f617f --- /dev/null +++ b/TodoApi/Users/AccessTokenResponse.cs @@ -0,0 +1,45 @@ +using System.Text.Json.Serialization; + +// Copied from https://github.com/dotnet/aspnetcore/blob/bad855959a99257bc6f194dd19ecd6c9aeb03acb/src/Shared/BearerToken/DTO/AccessTokenResponse.cs + +namespace TodoApi; + +internal sealed class AccessTokenResponse +{ + /// + /// The value is always "Bearer" which indicates this response provides a "Bearer" token + /// in the form of an opaque . + /// + /// + /// This is serialized as "token_type": "Bearer" using System.Text.Json. + /// + [JsonPropertyName("token_type")] + public string TokenType { get; } = "Bearer"; + + /// + /// The opaque bearer token to send as part of the Authorization request header. + /// + /// + /// This is serialized as "access_token": "{AccessToken}" using System.Text.Json. + /// + [JsonPropertyName("access_token")] + public required string AccessToken { get; init; } + + /// + /// The number of seconds before the expires. + /// + /// + /// This is serialized as "expires_in": "{ExpiresInSeconds}" using System.Text.Json. + /// + [JsonPropertyName("expires_in")] + public required long ExpiresInSeconds { get; init; } + + /// + /// If set, this provides the ability to get a new access_token after it expires using a refresh endpoint. + /// + /// + /// This is serialized as "refresh_token": "{RefreshToken}" using System.Text.Json. + /// + [JsonPropertyName("refresh_token")] + public required string RefreshToken { get; init; } +} diff --git a/TodoApi/Users/UsersApi.cs b/TodoApi/Users/UsersApi.cs index e02f5895..75da7d07 100644 --- a/TodoApi/Users/UsersApi.cs +++ b/TodoApi/Users/UsersApi.cs @@ -27,7 +27,7 @@ public static RouteGroupBuilder MapUsers(this IEndpointRouteBuilder routes) return TypedResults.ValidationProblem(result.Errors.ToDictionary(e => e.Code, e => new[] { e.Description })); }); - group.MapPost("/token", async Task> (UserInfo userInfo, UserManager userManager) => + group.MapPost("/token", async Task>> (UserInfo userInfo, UserManager userManager) => { var user = await userManager.FindByNameAsync(userInfo.Username); @@ -41,7 +41,7 @@ public static RouteGroupBuilder MapUsers(this IEndpointRouteBuilder routes) return TypedResults.SignIn(principal, authenticationScheme: BearerTokenDefaults.AuthenticationScheme); }); - group.MapPost("/token/{provider}", async Task> (string provider, ExternalUserInfo userInfo, UserManager userManager) => + group.MapPost("/token/{provider}", async Task>> (string provider, ExternalUserInfo userInfo, UserManager userManager) => { var user = await userManager.FindByLoginAsync(provider, userInfo.ProviderKey);