FirebaseAuth Defaultinstance is null / .net core - firebase

I have an ionic/angular frontend where I have the user registration via firebase. I already retrieve my firebase token, send it to my .net backend and verify the token with the [Authorize] annotation.
After authorization, I want to decode the token and use the id of the user for further processing.
Step get the token from the "Authorization" header
string authHeader = this.HttpContext.Request.Headers["Authorization"];
var decodedFirebaseToken = await fireBaseAuthenticationHelper.GetUserFromFirebaseIdAsync(authHeader.Substring("Bearer ".Length).Trim());
Step retrieve the decoded token
public async Task<FirebaseToken> GetUserFromFirebaseIdAsync(string token)
{
FirebaseToken decodedToken = await FirebaseAuth.DefaultInstance
.VerifyIdTokenAsync(token);
return decodedToken;
}
The problem now is that the FirebaseAuth.DefaultInstance is always null and throws a null pointer exception. I don't know where or how to initialize the DefaultInstance.
On the FirebaseAuth class is a comment:
public sealed class FirebaseAuth : IFirebaseService
{
//
// Summary:
// Gets the auth instance associated with the default Firebase app. This property
// is null if the default app doesn't yet exist.
public static FirebaseAuth DefaultInstance { get; }
So I am pretty sure I have to initialize it somewhere but I can't find where.

You have to initialize the SDK by creating a new FirebaseApp first. See the code samples in https://firebase.google.com/docs/admin/setup

Related

The getter 'uid' was called on null in flutter

I'm implementing firebase authentication in flutter application but while trying to get user uid , it is crashing and show noSuchMethodError uid is null , if anyone could help , it is deeply appreciated
That's how i init my variables
class _UserRegistrationState extends State<UserRegistration> {
FirebaseAuth auth;
DocumentReference reference;
Reference storage;
PickedFile imageUri;
final ImagePicker _imagePicker = new ImagePicker();
#override
void initState() {
super.initState();
auth = FirebaseAuth.instance;
// the uid is where the logcat is pointing too and it is null
reference = FirebaseFirestore.instance.collection('users').doc(auth.currentUser.uid);
storage = firebase_storage.FirebaseStorage.instance.ref('avatar').child(auth.currentUser.uid);
}
When you sign in to Firebase Authentication, the SDK automatically persists the user's credentials in local storage. When you restart the app, the SDK tries to restore the user's authentication state from the stored credentials. This requires that it calls the servers to get a new ID token, and for example to check if the account was deleted/disabled in the meantime.
Depending on the platform where you run your code, the calls to the server may have completed before your auth.currentUser runs, or not. To safely respond to the user state, always use an auth state listener as shown in the FlutterFire documentation on responding to auth state changes:
#override
void initState() {
super.initState();
auth = FirebaseAuth.instance;
FirebaseAuth.instance.authStateChanges().listen((User user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
reference = FirebaseFirestore.instance.collection('users').doc(auth.currentUser.uid);
storage = firebase_storage.FirebaseStorage.instance.ref('avatar').child(auth.currentUser.uid);
}
});
}
currentUser → User?
Returns the current User if they are currently signed-in, or null if not.
So most likely thing is that you are not logged in and therefore passing null to reference

Don't issue a token in Identity Server 4 when a user is set to inactive

We've recently implemented the ability to disable users in our application with an "Active" boolean field in the Identity.AspNetUsers table. Logging in to the back office system (an Angular application) is easily handled with an implicit flow -- simply check the field before calling PasswordSignInAsync.
We can't figure a way to stop a token being issued for any mobile devices using the sister application (written in Flutter) that calls the built in ID Server 4 endpoint /connect/token. Likewise, we can't stop the application from requesting, and then receiving, a valid refresh token. We can't hard delete the user as we have hard links to other tables in the database for auditing purposes.
Any help would be massively appreciated.
We're using DotNET Core 3,1.
EDIT: We're using the password grant type.
When the client asks for a new access token using the refresh token, then the RefreshTokenService is involved. by Customizing refresh token behavior you can lookup if the user is disabled and then reject thew new access token from being issued. See this page for more details about how to do this.
Alternatively you can in the class that implements IPersistedGrantStore add some code to lookup if the user is disabled and then return
return Task.FromResult<PersistedGrant>(null!);
When blocked.
When using the password grant with the built in /connect/token endpoint, you implement the interface ICustomTokenRequestValidator and add it as a Transient to the service collection. This has one method, ValidateAsync, and if the user referenced by your request is valid you simply return and the pipeline continues as normal. If your user is not valid you set the Result.IsError property on CustomTokenRequestValidationContext to true, and supply a string to Result.Error before you return so the token is then not issued.
Inject UserManager<T> and IHttpContextAccessor so you can access the username and user store from the method.
Here's an implementation:
public class CustomTokenRequestValidator : ICustomTokenRequestValidator
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly IHttpContextAccessor _httpContextAccessor;
private const string errorMessage = "invalid_username_or_password";
public CustomTokenRequestValidator(
UserManager<ApplicationUser> userManager
, IHttpContextAccessor httpContextAccessor)
{
_userManager = userManager;
_httpContextAccessor = httpContextAccessor;
}
public async Task ValidateAsync(CustomTokenRequestValidationContext context)
{
_httpContextAccessor.HttpContext.Request.Form.TryGetValue("username", out var userOut);
var u = userOut.ToString();
if(u != null)
{
var user = await _userManager.FindByEmailAsync(u);
if(user == null || !user.Active)
{
context.Result.IsError = true;
context.Result.Error = errorMessage;
}
} else
{
context.Result.IsError = true;
context.Result.Error = errorMessage;
}
return;
}
}

Firebase IDToken to Google OAuth2 access token in Unity

We use Firebase Auth in our Unity game and Google SignIn and need to access Google services like Google Classroom.
Firebase Auth gives us a JWT IdToken after signing in using this code https://firebase.google.com/docs/auth/admin/verify-id-tokens#unity
Firebase.Auth.FirebaseUser newUser = task2.Result;
var token = await newUser.TokenAsync(false);
I tried passing this token to Google Classroom service but it requires an OAuth2 AccessToken.
How I convert this JWT Firebase IdToken to an AccessToken that can be used by the GoogleClassroom API?
I am looking for the AccessToken to pass to the Google Classroom APIs
var credential = GoogleCredential.FromAccessToken(AccessToken);
var service = new ClassroomService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
I have tried the answer to this question but the service is returning 404.
You are trying to get google access token..!
You can simply get it by a simple API call.
IEnumerator GetAccessToken()
{
WWWForm form = new WWWForm();
form.AddField("client_id", "your_webClientId");
form.AddField("client_secret", "your_clientsecret");
form.AddField("grant_type", "authorization_code");
form.AddField("code", "your_authcode);
UnityWebRequest www = UnityWebRequest.Post("https://www.googleapis.com/oauth2/v4/token", form);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
}
else
{
//Access token response
GoogleData googleData =JsonUtility.FromJson<GoogleData>(www.downloadHandler.text);
Debug.LogError(googleData.access_token);
}
}
In the API success you can parse the response in to data model class.
NOTE:Do not chane "grant_type" field value.
[System.Serializable]
public class GoogleData
{
public string access_token;
public string token_type;
public int expires_in;
public string refresh_token;
}

How to re-validate token for multi-tenant ASP.NET Identity?

I have implemented a custom OAuthAuthorizationServerProvider to add a domain constraint for the account login. Everything was good. However, I met a problem that, once the user get the token, they can use it for whatever system they want. For example:
They request the TokenEndpointPath with proper username and password (assume it is the admin account of Tenant 1): http://localhost:40721/api/v1/account/auth and receive the Bearer Token.
Now they use it to access: http://localhost:40720/api/v1/info/admin, which is of Tenant 0. The request is considered Authorized.
I tried changing the CreateProperties method but it did not help:
public static AuthenticationProperties CreateProperties(string userName)
{
var tenant = DependencyUtils.Resolve<IdentityTenant>();
IDictionary<string, string> data = new Dictionary<string, string>
{
{ "userName", userName },
{ "tenantId", tenant.Tenant.Id.ToString() },
};
return new AuthenticationProperties(data);
}
I also tried overriding ValidateAuthorizeRequest, but it is never called in my debug.
Do I need to implement a check anywhere else, so the Token is only valid for a domain/correct tenant?
(NOTE: a tenant may have multiple domains, so it's great if I can manually perform an account check against correct tenant rather than sticking to a domain. However, it's a plus if I could do that, or else, simply limit the token to the domain is ok)
Not a direct answer to my question (since it's not inside ASP.NET Identity workflow), but the simplest fix I applied was to use ActionFilterAttribute instead.
public class DomainValidationFilter : ActionFilterAttribute
{
public override Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
// Other Code...
// Validate if the logged in user is from correct tenant
var principal = actionContext.ControllerContext.RequestContext.Principal;
if (principal != null && principal.Identity != null && principal.Identity.IsAuthenticated)
{
var userId = int.Parse(principal.Identity.GetUserId());
// Validate against the tenant Id of your own storage, and use this code to invalidate the request if it is trying to exploit:
actionContext.Response = actionContext.Request.CreateResponse(System.Net.HttpStatusCode.Unauthorized, "Invalid Token");
}
return base.OnActionExecutingAsync(actionContext, cancellationToken);
}
}
Then applies the Filter to all actions by registering it in either FilterConfig or WebApiConfig:
config.Filters.Add(new DomainValidationFilter());

How to authenticate an access token using OWIN OAuthBearerAuthentication?

What I want:
A token generator use OAuthAuthorizationServer and token consumer use OAuthBearerAuthentication (authenticate the access token).
Use OWIN pipeline to manage all stuff, token stuff and web api stuff.
What about the code:
public void Configuration(IAppBuilder app)
{
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AuthorizeEndpointPath = "/Authorize",
AllowInsecureHttp = true,
Provider = new OAuthAuthorizationServerProvider
{
OnGrantCustomExtension = GrantCustomExtension,
OnValidateClientRedirectUri = ValidateClientRedirectUri,
OnValidateClientAuthentication = ValidateClientAuthentication,
}
});
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
Provider = new OAuthBearerAuthenticationProvider
{
//Handles applying the authentication challenge to the response message.
ApplyChallenge=MyApplyChallenge,
//Handles processing OAuth bearer token.
RequestToken=MyRequestToken,
//Handles validating the identity produced from an OAuth bearer token.
ValidateIdentity = MyValidateIdentity,
}
});
app.UseWebApi(new WebApplication3.Config.MyWebApiConfiguration());
}
What's the question:
The 3 properties of OAuthBearerAuthenticationProvider,
ApplyChallenge, RequestToken and ValidateIdentity. How to
implement the 3 methods?
In the token authetication process, What I thought is to decrypt the access token, validate the token from the client, and if the token is validated, put the identities of the token to the HttpContext.Current.User.
The OAuthBearerAuthenticationProvider's responsibility is to fulfill the
previous steps. Am I right?
As you know, UseOAuthAuthorizationServer has the job of authenticating the user. Then, UseOAuthBearerAuthentication has the job of ensuring that only authenticated users can access your application. Often, these two jobs are assigned to different web application. It looks like your application is doing both.
There are certainly some cases were you need to override the default OAuthBearerAuthenticationProvider. Maybe you do, or maybe you don't In my case, ApplicationCookie didn't quite fit the scenario. So, I'm storing a 3rd party JWT token in a cookie, rather than the header, and using it to indicate that the user is authenticated to a web application. I also needed to redirect to my own login page, rather than provide a 401.
Here's an implementation that does both:
public class CustomOAuthBearerProvider : IOAuthBearerAuthenticationProvider
{
public Task ApplyChallenge(OAuthChallengeContext context)
{
context.Response.Redirect("/Account/Login");
return Task.FromResult<object>(null);
}
public Task RequestToken(OAuthRequestTokenContext context)
{
string token = context.Request.Cookies[SessionKey];
if (!string.IsNullOrEmpty(token))
{
context.Token = token;
}
return Task.FromResult<object>(null);
}
public Task ValidateIdentity(OAuthValidateIdentityContext context)
{
return Task.FromResult<object>(null);
}
}
I didn't need to do anything special in ValidateIdentity, but I needed to satisfy the interface.
To wire this up, tell your app to use JwtBearerAuthentication with your provider:
// controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AllowedAudiences = audiences.ToArray(),
IssuerSecurityTokenProviders = providers.ToArray(),
Provider = new CookieOAuthBearerProvider()
}
);

Resources