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

Added refresh endpoint for access token #120

Merged
merged 3 commits into from
Jan 23, 2025
Merged

Conversation

kiwimaja
Copy link
Collaborator

No description provided.

@kiwimaja kiwimaja added the enhancement New feature or request label Jan 23, 2025
@kiwimaja kiwimaja requested a review from LightJack05 January 23, 2025 12:07
@kiwimaja kiwimaja self-assigned this Jan 23, 2025
@@ -14,5 +14,6 @@ public static void MapEndpoints(WebApplication app)
app.MapPost("/authentication/login", Login.PostLogin).WithTags("Authentication").WithOpenApi();
app.MapPut("/authentication/changePassword", ChangePassword.PutChangePassword).WithTags("Authentication").WithOpenApi().RequireAuthorization("user");
app.MapPut("/authentication/logout", Logout.PutLogout).WithTags("Authentication").WithOpenApi().RequireAuthorization("user");
app.MapPut("/authentication/refreshAccess", RefreshEndpointAccessToken.PostRefreshAccessToken).WithTags("Authentication").WithOpenApi().RequireAuthorization("user");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the endpoint path to "authentication/refreshAccessToken" please

{

/// <summary>
/// Creates a new access token.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... based on a refresh token

return TypedResults.Unauthorized();
}

User? user = databaseHandle.Users.Where(u => u.Username == requestBody.UserName).FirstOrDefault();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You dont need to use a body here, just use the claims from the token to get the username


User? user = databaseHandle.Users.Where(u => u.Username == requestBody.UserName).FirstOrDefault();

// If no user is found matching the redentials, return 404.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be no possibility for that, since the user is authenticated using a refresh token. Still, should the user be null, just return unauthorized. This is not a login request.

{
databaseHandle.Database.EnsureCreated();

if (!AnonKeyBackend.Authentication.TokenActions.ValidateClaimsOnRequest(userClaimsPrincipal, databaseHandle))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set isRefreshRequest = true here

}

// Generate a new token and return it to the user.
Token refreshToken = tokenService.GenerateNewToken(user, "RefreshToken");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--


// Generate a new token and return it to the user.
Token refreshToken = tokenService.GenerateNewToken(user, "RefreshToken");
Token accessToken = tokenService.GenerateNewToken(user, "AccessToken");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass parent token uuid to this call

Ok<ApiDatastructures.Authentication.Login.AuthenticationLoginResponseBody>,
NotFound<ApiDatastructures.RequestError.ErrorResponseBody>,
UnauthorizedHttpResult>
PostRefreshAccessToken(ClaimsPrincipal userClaimsPrincipal, ApiDatastructures.Authentication.Login.AuthenticationLoginRequestBody requestBody, AnonKeyBackend.Authentication.TokenService tokenService, Data.DatabaseHandle databaseHandle)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please define your own return schemas in ApiDatastructures.

Copy link
Owner

@LightJack05 LightJack05 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, see comments for things that still need fixing.

@@ -0,0 +1,20 @@
namespace AnonKeyBackend.ApiDatastructures.Authentication.RefreshTokens;
Copy link
Owner

@LightJack05 LightJack05 Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally name the Namespace more something like "RefreshAccessToken" (make sure to rename the folder appropriately)

/// <summary>
/// Represents a token object in the response to a Refresh request.
/// </summary>
public class AuthenticationRefreshTokens
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the class to something like "AuthenticationRefreshAccessToken" to avoid name conflicts

/// <summary>
/// The body of the response to a Refresh request.
/// </summary>
public class AuthenticationRefreshTokensResponseBody
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the class to something like "AuthenticationRefreshAccessTokenResponseBody" to avoid name conflicts

/// <summary>
/// The token for refreshing the access token or the refresh token itself
/// </summary>
public AuthenticationRefreshTokens? RefreshToken { get; set; }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There wont be a RefreshToken returned by this request, so this property can be removed.

return TypedResults.Unauthorized();
}

User? userName = databaseHandle.Users.Where(u => u.Username == user.Identity.Name).FirstOrDefault();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This variable name may be misleading, as it implies type "string", while being "User?".
  2. You are missing a null check on user.Identity (formal requirement mostly...)

return TypedResults.Unauthorized();
}

string tokenUuid = user.Claims.First(c => c.Type == "TokenParent").Value;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The token used for authentication against this endpoint is a RefreshToken, use the TokenUuid claim instead of TokenParent. (TokenParent is not populated for refresh tokens)

Copy link
Owner

@LightJack05 LightJack05 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

@LightJack05 LightJack05 merged commit 0e2e264 into beta Jan 23, 2025
4 checks passed
@LightJack05 LightJack05 deleted the refresh-endpoint-access branch January 23, 2025 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants