Comments (14)
Are you sure you'd need to refresh the third party tokens as well? From what I understand from the docs and after playing with custom tokens is that any third party token is just used once initially, to receive a firebase token. That one can then be refreshed calling:
https://securetoken.googleapis.com/v1/token?key={apiKey}
Form data:
grant_type:refresh_token
refresh_token:{refreshToken}
Response:
{
"access_token": "{seems to be identical with the idToken}",
"expires_in": "3600",
"token_type": "Bearer",
"refresh_token": "{refreshToken. Seems to the the same as we passed in}",
"id_token": "{newToken}",
"user_id": "{UID}",
"project_id": "{projectId}"
}
So shouldn't it be enough to check before any query/insert if the token is about to expire. And if so, do a refresh first, then go on doing the query/insert?
from firebase-authentication-dotnet.
If you manage to implement it you can do a PR and I'll merge it into this lib ;)
from firebase-authentication-dotnet.
You need to call SignIn method again, refreshing is not supported. This is due to multiple possible sources of the underlying oauth login data (facebook / google / etc.) and the lib would need to handle refreshing that as well, which would required a lot more work.
from firebase-authentication-dotnet.
Ok, at the moment i implemented this by calling SignIn automatically before ExpiresIn happens, but this is far from ideal. @bernhardgessler 's idea sounds good to test out in a fork if i have the time.
from firebase-authentication-dotnet.
Swamped with other projects atm, but let's see in the near future :)
from firebase-authentication-dotnet.
Calling https://securetoken.googleapis.com/v1/token?key={apiKey} with Firebase API Key produces a 400 Bad Request error:
{
"error": {
"code": 400,
"message": "API key not valid. Please pass a valid API key.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.Help",
"links": [
{
"description": "Google developers console",
"url": "https://console.developers.google.com"
}
]
}
]
}
}
from firebase-authentication-dotnet.
You need to pass some info in the body. See here
Basically, the folllowing code (in the Auth Provider) is working:
public async void RefreshAuth(FirebaseAuthLink auth)
{
var GoogleRefreshAuth = "https://securetoken.googleapis.com/v1/token?key={0}";
var content = $"{{\"grant_type\":\"refresh_token\", \"refresh_token\":\"{auth.RefreshToken}\"}}";
var response = await this.client.PostAsync(new Uri(string.Format(GoogleRefreshAuth, this.authConfig.ApiKey)), new StringContent(content, Encoding.UTF8, "application/json"));
string responseData = await response.Content.ReadAsStringAsync();
FirebaseAuthLink authNew = JsonConvert.DeserializeObject<FirebaseAuthLink>(responseData);
}
But the response names things differently. expires_in
instead of expiresIn
etc. So I'm still thinking how to solve this most elegantly. Also I need to find a way to automate it. .WithAuth
only takes the token string. So it won't know if the token is still valid. Either we'd change that to requiring the full FirebaseAuthLink
or I'm thinking about remodeling FirebaseAuth
, making FirebaseToken
a real property that checks itself for expiration. When created initially by the AuthProvider, FirebaseAuth
could store it's creation date and a reference to the IFirebaseAuthProvider
. Then once it detects that its expiring, it could contact that AuthProvider again to renew the token and then update itself.
Thoughts @itswisdomagain @sessio @bezysoftware ?
I'll try implementing this tonight. I can technically make it work, no problem. Just not sure if this is elegant... Also @bezysoftware mentioned somewhere else, that it's planned to restructure Authenticating to get rid of .WithAuth()
if I remember that correctly...
from firebase-authentication-dotnet.
Correct, as of v2.0.1 the "WithAuth
" method is no longer accessible. Instead you need to specify an Action<Task<string>>
which asynchronously returns this token string. https://github.com/step-up-labs/firebase-database-dotnet#authentication
This way the process of checking the token validity can be delegated to this library easily.
However I am curious - lets say I login with an OAuth token (e.g. from facebook) and I get a firebase token. What happens if the underlying OAuth token expires? Can I still refresh the Firebase token only (without refreshing the facebook token myself)? Does the google service handle that?
from firebase-authentication-dotnet.
Didn't notice that you already pushed the update. At least I remembered correctly ;)
From what I understand about Firebase Authentication and what I pieced together e.g. from threads like this one, I keep hearing about being 'logged in forever'. This only makes sense if the token can be renewed without consulting the third party again.
I suppose the third party token is used initially for being sure about who a user is. Then the uniform firebase token is issued, to make different providers transparent. Otherwise there would be no good reason either why to change a custom token for another token.
Observing their official JS client for a couple of hours, this is what happens. It calls the above servivce every time the token is older than 3600 sec.
Looking at your new approach with the factory the issue I see there is that this code is executed every time I query Firebase. You propose to authenticate inside that method. But once I'm authenticated I don't want to authenticate again. Imagine I'm calling my own auth server which lets say takes 5 seconds. So on every query I'll spend 5 seconds waiting for being authenticated, unless I actually authenticate before, store the FirebaseAuth and inside that method only pass my token / renew my token. But for doing so, I'm just as far as I was before...
How about the following:
- Client construktor accepts FireBaseAuth as param:
var authProvider = new FirebaseAuthProvider(new FirebaseConfig(FirebaseApiKey));
var facebookAccessToken = "<login with facebook and get oauth access token>";
var auth = await authProvider.SignInWithOAuthAsync(FirebaseAuthType.Facebook, facebookAccessToken);
var firebaseClient = new FirebaseClient(
"<URL>",
new FirebaseOptions
{
Auth= auth
});
...
Internally, where currently the factory is called, you just get the token from the FirebaseAuth object:
public async Task<string> BuildUrlAsync()
{
// if token factory is present on the parent then use it to generate auth token
if (this.Client.Options.Auth != null)
{
var token = this.Client.Options.FirebaseToken;
return this.WithAuth(token).BuildUrl(null);
}
return this.BuildUrl(null);
}
The actual checking happens inside the Auth object:
public class FirebaseAuth
{
private IFirebaseAuthProvider _authProvider;
private DateTime _lastRenewal;
private string _firebaseToken;
[JsonProperty("idToken")]
public string FirebaseToken
{
get
{
if(DateTime.Now >= DateTime.Now.AddSeconds(this.ExpiresIn)
{
// Expired contact Authprovider to renew
this._authProvider.RenewToken(this);
}
return this._firebaseToken;
}
set
{
this._firebaseToken = value;
}
}
[JsonProperty("refreshToken")]
public string RefreshToken { get; set; }
[JsonProperty("expiresIn")]
public int ExpiresIn { get; set; }
public User User { get; set; }
}
Last step is to add RenewToken(FirebaseAuth currentAuth)
inside the AuthProvider. Similar to the proposal in my last message. Just actually updating the auth object.
I think this would be a cleaner approach. What do you think?
from firebase-authentication-dotnet.
This would of course work with your current implementation as well. Just a bit extra code actually:
var authProvider = new FirebaseAuthProvider(new FirebaseConfig(FirebaseApiKey));
var facebookAccessToken = "<login with facebook and get oauth access token>";
var auth = await authProvider.SignInWithOAuthAsync(FirebaseAuthType.Facebook, facebookAccessToken);
var firebaseClient = new FirebaseClient(
"<URL>",
new FirebaseOptions
{
AuthTokenAsyncFactory = () => Task.FromResult(auth.FirebaseToken)
});
So I guess the key part would be the implementation within the Auth object and the Auth provider...
from firebase-authentication-dotnet.
@bezysoftware,
" lets say I login with an OAuth token (e.g. from facebook) and I get a firebase token. What happens if the underlying OAuth token expires? Can I still refresh the Firebase token only (without refreshing the facebook token myself)?"
Yes. You only need the refreshToken from Firebase to refresh a the Firebase token.
"you need to specify an Action<Task> which asynchronously returns this token string. This way the process of checking the token validity can be delegated to this library easily."
True. Here's a working code I've been using, yeah, the code needs some help, but it works as it's supposed to, for now. I'll clean it up later.
A method to check the current token's validity and refresh it if necessary.
`
if (FirebaseUser == null)
return null;
if (FirebaseUser.TokenExpiry <= DateTime.Now)
{
//refresh token
DoRefreshToken();
}
return FirebaseUser.FirebaseToken;
`
FirebaseUser is a class I created similar to FirebaseAuthLink (I just didn't like the name)
`
public class FirebaseUser
{
public DateTime TokenExpiry { get; private set; }
public string FirebaseToken { get; private set; }
public string FirebaseRefreshToken { get; private set; }
public string FirebaseUID { get; private set; }
public FirebaseUser(Firebase.Auth.FirebaseAuthLink user)
{
this.FirebaseUID = user.User.LocalId;
UpdateToken(user.FirebaseToken, user.RefreshToken, user.ExpiresIn);
}
public FirebaseUser(string token, int secondsExpiry, string refreshToken, string uid)
{
this.FirebaseUID = uid;
UpdateToken(token, refreshToken, secondsExpiry);
}
public void UpdateToken(string token, string refreshToken, int secondsExpiry)
{
this.FirebaseToken = token;
this.TokenExpiry = DateTime.Now.AddSeconds(secondsExpiry - 300); //5 minutes difference just to be safe
this.FirebaseRefreshToken = refreshToken;
App.SaveFirebaseUserDetailsSecurely(this); // I do this to enable me refresh the token every the time the app opens and keep the user signed in
}
}
`
This is where the real deal is anyways: DoRefreshToken
`
public static void DoRefreshToken()
{
var client = new RestClient("https://securetoken.googleapis.com");
var request = new RestRequest("/v1/token?key=" + GoogleAuthAPI + "&grant_type=refresh_token&refresh_token=" +
FirebaseUser.FirebaseRefreshToken, Method.POST);
var response = client.Execute(request);
var auth = new
{
access_token = "",
expires_in = 0,
token_type = "",
refresh_token = ""
};
auth = JsonConvert.DeserializeAnonymousType(response.Content, auth);
FirebaseUser.UpdateToken(auth.access_token, auth.refresh_token, auth.expires_in);
}
`
Putting it all together:
Func<Task> FirebaseUserTokenGenerator = () => Task.FromResult(GetUserToken());
There. Works fluidly.
Please let me know if any questions or concerns.
from firebase-authentication-dotnet.
I do agree with @bernhardgessler, we could do this to make everything appear seamless:
Add a Func<Task> to Firebase.Auth.FirebaseAuth
All token refresh processes can now be included in the FirebaseAuth class.
Use the Func<Task> in the FirebaseAuth object as the AuthTokenAsyncFactory for the FirebaseClient constructor where necessary.
I could do a PR. Does that sound cool?
from firebase-authentication-dotnet.
I created a PR #14 for refreshing the token. The token refreshing code comes from @bernhardgessler but usage is slightly different - see the comment on the PR.
Let me know your thoughts, I think it should be usable and easy to integrate with FirebaseOptions, you would always just call GetFreshAuthAsync
to get the latest token. Saving the token & loading it from storage should be simple as well.
from firebase-authentication-dotnet.
Merged and published to nuget
from firebase-authentication-dotnet.
Related Issues (20)
- wpf with dependency injection HOT 1
- (Enchancement) Support Local Storage & Async for IUserRepository HOT 1
- Possibility to check user password HOT 1
- Question: do you not support sign in with custom token? HOT 1
- Email verification HOT 7
- Posibility to change the token expiration HOT 1
- Phone Authentication
- Exception occured during Firebase Http request. HOT 1
- Check if DisplayName already exists HOT 1
- Need Help with login with Google in .NET MAUI HOT 1
- Email Verification Implementation Help HOT 1
- [Endpoints Migration] : identitytoolkit v3 needs to be migrated to something else HOT 1
- Is there a way to get the last time user logged in?
- Create Email and Password issue in .Net MAUI
- [.NET MAUI] How implement "OpenBrowserAndWaitForRedirectToAuthDomain" HOT 2
- I can't get FetchSignInMethodsForEmailAsync to work HOT 2
- How to persist authentication across app restarts ? HOT 6
- Allow FirebaseAuthConfig.RedirectUri to be configurable
- Observed in version 3.7.2 : Parsing error when the password ends (or maybe contains also) a backslash \ HOT 2
- How do you set a photo Url in version 4.1.0?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from firebase-authentication-dotnet.