Skip to content

Commit

Permalink
Introduce VerifyTokenHash to support the PKCE flow for email signup (#98
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbakker committed Jun 28, 2024
1 parent 9380ac3 commit 7854aa8
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 1 deletion.
16 changes: 16 additions & 0 deletions Gotrue/Api.cs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,22 @@ public Task<BaseResponse> SendMobileOTP(string phone)
return Helpers.MakeRequest<Session>(HttpMethod.Post, $"{Url}/verify", data, Headers);
}

/// <summary>
/// Verify token hash used in an email confirmation link.
/// </summary>
/// <param name="tokenHash">The token hash used in an email confirmation link</param>
/// <param name="type">Type of verification, e.g. email.</param>
/// <returns></returns>
public Task<Session?> VerifyTokenHash(string tokenHash, EmailOtpType type)
{
var data = new Dictionary<string, string>
{
{ "token_hash", tokenHash },
{ "type", Core.Helpers.GetMappedToAttr(type).Mapping }
};
return Helpers.MakeRequest<Session>(HttpMethod.Post, $"{Url}/verify", data, Headers);
}

/// <summary>
/// Sends a reset request to an email address.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions Gotrue/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,26 @@ public Task<ProviderAuthState> SignIn(Provider provider, SignInOptions? options
return null;
}

/// <inheritdoc />
public async Task<Session?> VerifyTokenHash(string tokenHash, EmailOtpType type = EmailOtpType.Email)
{
if (!Online)
throw new GotrueException("Only supported when online", Offline);

DestroySession();

var session = await _api.VerifyTokenHash(tokenHash, type);

if (session?.AccessToken != null)
{
UpdateSession(session);
NotifyAuthStateChange(SignedIn);
return session;
}

return null;
}

/// <inheritdoc />
public Task<ProviderAuthState> LinkIdentity(Provider provider, SignInOptions options)
{
Expand Down
4 changes: 3 additions & 1 deletion Gotrue/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ public enum EmailOtpType
[MapTo("recovery")]
Recovery,
[MapTo("email_change")]
EmailChange
EmailChange,
[MapTo("email")]
Email
}

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions Gotrue/Interfaces/IGotrueApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public interface IGotrueApi<TUser, TSession> : IGettableHeaders
Task<TUser?> UpdateUserById(string jwt, string userId, UserAttributes userData);
Task<TSession?> VerifyMobileOTP(string phone, string token, MobileOtpType type);
Task<TSession?> VerifyEmailOTP(string email, string token, EmailOtpType type);
Task<TSession?> VerifyTokenHash(string tokenHash, EmailOtpType type);
Task<BaseResponse> Reauthenticate(string userJwt);
ProviderAuthState GetUriForProvider(Provider provider, SignInOptions? options = null);
Task<Session?> ExchangeCodeForSession(string codeVerifier, string authCode);
Expand Down
8 changes: 8 additions & 0 deletions Gotrue/Interfaces/IGotrueClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,14 @@ public interface IGotrueClient<TUser, TSession> : IGettableHeaders
/// <returns></returns>
Task<TSession?> VerifyOTP(string email, string token, EmailOtpType type = EmailOtpType.MagicLink);

/// <summary>
/// Log in a user given the token hash used in an email confirmation link.
/// </summary>
/// <param name="tokenHash"></param>
/// <param name="type"></param>
/// <returns></returns>
Task<TSession?> VerifyTokenHash(string tokenHash, EmailOtpType type = EmailOtpType.Email);

/// <summary>
/// Links an oauth identity to an existing user.
///
Expand Down
9 changes: 9 additions & 0 deletions Gotrue/Interfaces/IGotrueStatelessClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,15 @@ public interface IGotrueStatelessClient<TUser, TSession>
/// <returns></returns>
Task<TSession?> VerifyOTP(string email, string otpToken, StatelessClientOptions options, EmailOtpType type = EmailOtpType.MagicLink);

/// <summary>
/// Log in a user given the token hash used in an email confirmation link.
/// </summary>
/// <param name="tokenHash"></param>
/// <param name="options"></param>
/// <param name="type"></param>
/// <returns></returns>
Task<TSession?> VerifyTokenHash(string tokenHash, StatelessClientOptions options, EmailOtpType type = EmailOtpType.Email);

/// <summary>
/// Retrieve the current settings for the Gotrue instance.
/// </summary>
Expand Down
13 changes: 13 additions & 0 deletions Gotrue/StatelessClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,19 @@ public async Task<bool> SignOut(string accessToken, StatelessClientOptions optio
return null;
}

/// <inheritdoc />
public async Task<Session?> VerifyTokenHash(string tokenHash, StatelessClientOptions options, EmailOtpType type = EmailOtpType.Email)
{
var session = await GetApi(options).VerifyTokenHash(tokenHash, type);

if (session?.AccessToken != null)
{
return session;
}

return null;
}

/// <inheritdoc />
public async Task<User?> Update(string accessToken, UserAttributes attributes, StatelessClientOptions options)
{
Expand Down

0 comments on commit 7854aa8

Please sign in to comment.