Skip to content

Custom Token signin support #207

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Auth/FirebaseAuthClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,18 @@ public async Task<FetchUserProvidersResult> FetchSignInMethodsForEmailAsync(stri
return new FetchUserProvidersResult(email, response.Registered, response.SigninMethods, response.AllProviders);
}

public async Task<UserCredential> SignInWithCustomTokendAsync(string customToken)
{
await this.CheckAuthDomain().ConfigureAwait(false);

var provider = (CustomTokenProvider)this.config.GetAuthProvider(FirebaseProviderType.CustomToken);
var result = await provider.SignInUserAsync(customToken).ConfigureAwait(false);

this.SaveToken(result.User);

return result;
}

public async Task<UserCredential> SignInWithEmailAndPasswordAsync(string email, string password)
{
await this.CheckAuthDomain().ConfigureAwait(false);
Expand Down
5 changes: 4 additions & 1 deletion src/Auth/FirebaseProviderType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public enum FirebaseProviderType
[EnumMember(Value = "phone")]
Phone,

Anonymous
[EnumMember(Value = "customtoken")]
CustomToken,

Anonymous
}
}
89 changes: 89 additions & 0 deletions src/Auth/Providers/CustomTokenProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using Firebase.Auth.Requests;
using System.Linq;
using System.Threading.Tasks;
using static Firebase.Auth.Providers.EmailProvider;

namespace Firebase.Auth.Providers
{
public class CustomTokenProvider : FirebaseAuthProvider
{
private SignInWithCustomToken signInWithCustomToken;
private GetAccountInfo getAccountInfo;

internal override void Initialize(FirebaseAuthConfig config)
{
base.Initialize(config);

this.signInWithCustomToken = new SignInWithCustomToken(config);
this.getAccountInfo = new GetAccountInfo(this.config);
}

public static AuthCredential GetCredential(string customToken)
{
return new CustomTokenCredential
{
ProviderType = FirebaseProviderType.CustomToken,
CustomToken = customToken
};
}

public Task<UserCredential> SignInUserAsync(string customToken)
{
return this.SignInWithCredentialAsync(GetCredential(customToken));
}

public override FirebaseProviderType ProviderType => FirebaseProviderType.CustomToken;

protected internal override async Task<UserCredential> SignInWithCredentialAsync(AuthCredential credential)
{
var ec = (CustomTokenCredential)credential;

var response = await this.signInWithCustomToken.ExecuteAsync(new SignInWithCustomTokenRequest
{
Token = ec.CustomToken,
ReturnSecureToken = true
}).ConfigureAwait(false);

var user = await this.GetUserInfoAsync(response.IdToken).ConfigureAwait(false);
var fc = new FirebaseCredential
{
ExpiresIn = response.ExpiresIn,
IdToken = response.IdToken,
RefreshToken = response.RefreshToken,
ProviderType = FirebaseProviderType.EmailAndPassword
};

return new UserCredential(new User(this.config, user, fc), ec, OperationType.SignIn);
}

protected internal override Task<UserCredential> LinkWithCredentialAsync(string idToken, AuthCredential credential)
{
// Anonnymouse accounts or relinking not supported with this method
throw new System.NotSupportedException();
}

private async Task<UserInfo> GetUserInfoAsync(string idToken)
{
var getResponse = await this.getAccountInfo.ExecuteAsync(new IdTokenRequest { IdToken = idToken }).ConfigureAwait(false);
var user = getResponse.Users[0];

return new UserInfo
{
DisplayName = user.DisplayName,
Email = user.Email,
IsEmailVerified = user.EmailVerified,
Uid = user.LocalId,
PhotoUrl = user.PhotoUrl,
IsAnonymous = false
};
}

internal class CustomTokenCredential : AuthCredential
{
public string CustomToken { get; set; }
}
}



}
8 changes: 6 additions & 2 deletions src/Auth/Requests/Endpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ internal static class Endpoints
public const string GoogleCreateAuthUrl = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/createAuthUri?key={0}";
public const string GoogleProjectConfighUrl = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/getProjectConfig?key={0}";
public const string GoogleUpdateUserPassword = "https://identitytoolkit.googleapis.com/v1/accounts:update?key={0}";
}
}
public const string GoogleSignInWithCustomToken = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key={0}";



}
}
31 changes: 31 additions & 0 deletions src/Auth/Requests/SignInWithCustomToken.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace Firebase.Auth.Requests
{
public class SignInWithCustomTokenRequest
{
public string Token { get; set; }

public bool ReturnSecureToken { get; set; }
}

public class SignInWithCustomTokenResponse
{
public string IdToken { get; set; }

public string RefreshToken { get; set; }

public int ExpiresIn { get; set; }
}

/// <summary>
/// Uses a custom token generated in a different backend (server) proces to login to firebase.
/// see: https://firebase.google.com/docs/auth/admin/create-custom-tokens
/// </summary>
public class SignInWithCustomToken : FirebaseRequestBase<SignInWithCustomTokenRequest, SignInWithCustomTokenResponse>
{
public SignInWithCustomToken(FirebaseAuthConfig config) : base(config)
{
}

protected override string UrlFormat => Endpoints.GoogleSignInWithCustomToken;
}
}