I am writing an Android application and I am trying to log users in anonymously so they don't have to go through any sort of registration process. I am storing their anonymous user ID in shared preferences, and when the application opens, I am trying to log them in based on that user ID. I am trying to figure out the correct way to do this, as there doesn't seem to be an auth function that just takes in a UID. Currently I have it using auth(), but I don't feel like that is correct.
Here is some sample code:
String userID = getUserID();
if(userID.equals("NOT_FOUND")) {
ref.authAnonymously(new Firebase.AuthResultHandler() {
#Override
public void onAuthenticated(AuthData authData) {
//successful authentication
//save auth data
SharedPreferences prefs = getSharedPreferences(
"USER_ID", Context.MODE_PRIVATE);
String id = authData.getUid();
prefs.edit().putString("USER_ID", id).commit();
}
#Override
public void onAuthenticationError(FirebaseError firebaseError) {
//unsuccessful authentication
}
});
} else {
ref.auth(userID, new Firebase.AuthListener() {
...
You're creating a new authentication session each and every time you invoke FirebaseRef.authAnonymously(...). This method only needs to be invoked once, after which the user will authenticated upon page refreshes. Also note that you do not need to call FirebaseRef.auth() again once restarting the application, as that piece is automatically handled for you.
If you'd like to check for the current authentication state of the user, and only then create a new authentication session if the user is not currently authenticated, use the synchronous accessor for authentication state FirebaseRef.getAuth().
Lastly, once you create an anonymous authentication session, no new sessions may ever be created with the same uid. That session will live until your predefined session expiration time (configured in your account dashboard) or until your user logs out, after which that uid is permanently retired.
Related
My security architecture consists of an Identity Server, JS Client and an external provider. The Identity Server uses authorization code flow.
A simplified login process looks as follows: User clicks login in the JS Client -> redirected to Identity Server -> redirected to external provider. I then use the external provider to authenticate the user. When sucessfully redirected back to my Identity Server I then check in a database if the user is active or not. This happens in the AccountController:
[HttpGet]
[Route("callback")]
public async Task<IActionResult> Callback()
{
var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
...
var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";
// My check if user is active or not
var isActive = await IsActiveAsync(providerUserId);
if (!isActive)
{
var errorRedirectUri = "https://127.0.0.1/error_page";
return Redirect(errorRedirectUri);
}
var context = await Interaction.GetAuthorizationContextAsync(returnUrl);
await Events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, providerUserId, subjectId, true, context?.Client.ClientId));
return Redirect(returnUrl);
}
If the user is active, the flow works perfectly. Access and refresh tokens are created, user is signed into the Identity Server and redirected back to the client. I am having issues in handling the case, where the user sucessfully logged in to the external provider but is not active in my database. In this case I want to redirect to a error page of the client.
An obvious way to do it, is to configure a error redirect uri, to which the user is redirected to in the mentioned scenario. But this does not feels like the proper way.
I also considered implementing the ProfileService.IsActiveAsync(...) method, but this just resulted in redirecting the user back to the external provider login after setting context.IsActive = false;. With no option of returning to the JS Client without valid credentials of an active user.
public async Task IsActiveAsync(IsActiveContext context)
{
// My check if user is active or not
context.IsActive = await IsActiveAsync(context.Subject);
}
So my question is: What is the apropriate way of redirecting the user to a client-side error page when the user was sucessfully authenticated at the external provider but was not marked as active in my own database?
I am accessing my backend with an access token obtained from firebase auth the following way:
login via email & password
receive the current user object
obtain the token from the user object
store the token locally to allow furher access to my backend (which uses firebase admin to validate the token)
This works, as long as the access token is stale.
This may as well work, if the application remains open and an 403 due to an expired token can be catched (I can just reuse the current user object to obtain a new token). However, if the token expires while the app is closed, opening it again (no more user object) results in forcing the user to reenter its credentials, does it?
One way that came to my mind was using the custom tokens functionality:
I could send the refresh token to the client after a login, which then stores it and would use it to log in (in an automatic manner) instead of using the credentials.
But the word "custom" made me think that I am on the wrong way somehow. There surely must be an easy way to do this with the intended functions.
Can any one help me out with this?
Greetings,
Codehai
Using this listener refreshes the token automatically, won't work in editor.
For my code to work, somehow I have to add TaskScheduler.FromCurrentSynchronizationContext() on all Firebase Tasks..
void Start()
{
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.IdTokenChanged += IdTokenChanged;
}
void IdTokenChanged(object sender, System.EventArgs eventArgs)
{
Firebase.Auth.FirebaseAuth senderAuth = sender as Firebase.Auth.FirebaseAuth;
if (senderAuth == auth && senderAuth.CurrentUser != null && !fetchingToken)
{
fetchingToken = true;
senderAuth.CurrentUser.TokenAsync(true).ContinueWith(
task =>
{
if (task.IsCanceled)
{
Debug.Log("canceled");
}
if (task.IsFaulted)
{
foreach (var errors in task.Exception.InnerExceptions)
{
Debug.Log(errors.InnerException.Message);
}
}
Debug.Log("New Token: " + task.Result);
// save task.Result
fetchingToken = false;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
private void OnDestroy()
{
auth.IdTokenChanged -= IdTokenChanged;
}
I am using Firebase authentication in my app and signing up a user with email and password. I want to get other users details (separate from the logged-in user) as well while a user is signed in with their own account. How can I get that information?
Values like email, display name and id (specific to authentication system) are available off of the Firebase User object. You can get a reference to the current logged in user off of the FIRAuth class. I provided links and class names for iOS, but other platforms are similarly structured.
If you want to store additional data for users, I would recommend including a users root node, using the uid off of the Firebase User object as the key for users child nodes.
//create user
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(SignupActivity.this, new OnCompleteListener < AuthResult > () {
#Override
public void onComplete(#NonNull Task < AuthResult > task) {
Toast.makeText(SignupActivity.this, "createUserWithEmail:onComplete:" + task.isSuccessful(), Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Toast.makeText(SignupActivity.this, "Authentication failed." + task.getException(),
Toast.LENGTH_SHORT).show();
} else {
String user_id = auth.getCurrentUser().getUid();
DatabaseReference current_user_db = _Database.child(user_id);
current_user_db.child("name").setValue(name);
current_user_db.child("image").setValue("default");
startActivity(new Intent(SignupActivity.this, ProfileActivity.class));
finish();
}
}
});
}
});
It's not a security issue, but just a mean of how you treat personal information. You can store what you want in firebase so you can easily store when the user login his/her avatar url (aka facebook url) or just id or any other infos anyway, then retrieve it.
If you need to retrieve infos of users which are not using your apps beside, thden you can also easily via the facebook sdk with user permission of course. take care–
I'm using ASP.NET Identity 2 authentication via OWIN middlewear. I've created a new project using the template so initially started with the default generated code but have changed it a bit (taken out entity framework and wired in my own existing authentication). This is all working.
What I'd now like to do is execute code after a user logs in via a saved cookie. I've had a look at ConfigureAuth in the Startup.Auth.cs file which I've configured as follows:
public void ConfigureAuth(IAppBuilder app) {
// Configure the user manager and signin manager to use a single instance
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider {
OnResponseSignIn = ctx => {
Log.Trace("On Response Sign In.");
},
OnResponseSignedIn = ctx => {
Log.Trace("On Response Signed In.");
},
OnValidateIdentity = async ctx => {
Log.Trace("On Validate Identity.");
}
}
});
}
From this I can see that OnResponseSignIn and OnResponseSignedIn are hit only during actual logins when the user enters their username and password. They are not hit when the user is authenticated via saved cookie.
OnValidateIdentity is hit regardless of whether the user authenticated via username/password or saved cookie and it's hit for every request they make.
What I'd like is to execute code just once after a login via cookie. Does anyone know how to do this? If not, I guess another option is to put code in OnValidateIdentity but in an if statement that will prevent it being run unless its the first call after the cookie authentication. Can anyone think of how to achieve that? All I can think of is to set a variable in Session after the code is first run and check for it's presence to prevent it being re-run?
It can probably be done by using a session variable as a flag, and only do your thing when it is not set.
OnValidateIdentity = async context => {
if (HttpContext.Current.Session["Refreshed"] == null)
{
/** do your thing **/
...
HttpContext.Current.Session["Refreshed"] = new object();
}
}
Here is my Scenario.
I have authentication web-services exposed by another domain. Now I want user name and password to be sent to that external domain for authentication. and when user is authenticated (returned true), I want the ASP.net to take that authentication further and let the user in and provide me all the asp.net standard utilities accessible, like currentuser, Isauthorized, Roles etc, for the user, authenticated. I hope this make sense.
This is not a problem. You have a variety of options available to you. One approach is to blend Forms Authentication with your own security model.
The basic idea is to let Forms Auth create and manage a ticket (in the form of an encrypted ticket) for the logged-in user. The ticket is used to determine whether or not someone is logged in, and who they are. You can then mix in any additional security related logic on top of that.
To process the login request, you just have a controller and action like you normally would. Note: in the example below, I am making some assumptions about LoginViewModel, the service you are using to authenticate, and the object it returns if any. You'll have to sub in your actual logic.
public ActionResult Login(LoginViewModel model)
{
// make sure the user filled out the login fields correctly
if (!ModelState.IsValid) return View(model);
// authenticate the user here
var authenticatedUser = AuthorizeUserUsingRemoteWebService(model.Username, model.Password);
if (authenticatedUser.IsAuthenticated)
{
// create forms auth ticket cookie and redirect to the home page
FormsAuthentication.SetAuthCookie(authenticatedUser.Username);
return RedirectToAction("Index", "Home");
}
// authentication failed, so show the login page again
return View(model);
}
In addition to that, you may have an HTTP module that handles the AuthenticateRequest event. Your module will be registered after the Forms Auth HTTP module, so it will have already processed whether or not the user is logged in. What you want to do is look up additional information if they are logged in, to get roles and such.
public class CustomAuthHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.AuthenticateRequest += new EventHandler(OnAuthenticateRequest);
}
void OnAuthenticateRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = appObject.Context;
// user isn't logged in, so don't do anything else
if (!context.User.Identity.IsAuthenticated) return;
// look up the roles for the specified user, returning the role names as an array of strings
string[] roles = LookupUserRolesFromWebService(context.User.Identity.Name);
// replace the current User principal with a new one that includes the roles we discovered for that user.
context.User = new GenericPrincipal(new GenericIdentity(context.User.Identity.Name), roles);
}
}
You'll register the HTTP module in your web.config:
<httpModules>
<add name="CustomAuthHttpModule"
type="MyAssembly.CustomAuthenticationModule, MyAssembly" />
</httpModules>
You can now use the User object in your MVC controllers and views, the AuthenticatedAttribute, etc.
However, I'd recommend that you cache the results of looking up a user's roles so you don't hammer your web service. I'll leave that up to you.
You can you use Security Token Service for your application. Setup a Windows Identity Foundation SDK and find examples in sdk directory (for me it is "C:\Program Files (x86)\Windows Identity Foundation SDK\v4.0\Samples\End-to-end\Federation for Web Apps"). One of them ( named "Federation for Web Apps") implement your case for AD authentication.