1

I want to log users automatically if they click a link in an email, e.g. example.com/action?_ul=blah-guid. It would detect the '_ul' and automatically login the user. The url can be one of many different ones, so I want to detect if the query string param is present and automatically log them in using this special key if it is.

I've previously done this with the old identity provider in Global.asax.cs using Application_BeginRequest, e.g.

protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (Request["_ul"] != null)
    {
        var userService = new UserService();
        userService.QuickLogin(Request["_ul"]);
    }
}

However, in this project we're using Asp.Net Identity and it seems the OwinStartup is happening after this point and is throwing an error:

No owin.Environment item was found in the context.

This happens in the initialisation of the service:

    public UserService()
    {
        signInManager = HttpContext.Current.GetOwinContext().Get<ApplicationSignInManager>();
    }

I tried using an ActionFilter but this happens after authentication.

I'm unsure how to do this in Asp.Net Identity, I want to keep normal forms authentication, but also detect if there is a particular query string value, log out if they're presently logged in, then log in using the special key.

What's the correct way to do this additional login check?

1 Answer 1

1

You need to implement AuthorizeAttribute. I've done something very similar to what you are trying to do:

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Web;
using System.Web.Mvc;


public class TokenAuthenticationAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var providedToken = filterContext.Controller.ValueProvider.GetValue("_ul").AttemptedValue;

        // Here check if your provided token is correct one and indeed authenticates user

        var user = // get your ApplicationUser based on your token

        var userManager = HttpContext.Current.GetOwinContext().Get<ApplicationUserManager>();

        // this might be different in your code. Basically you need to crate ClaimsIdentity from ApplicationUser object
        var identity = user.CreateIdentity(userManager, DefaultAuthenticationTypes.ApplicationCookie); 

        var claimsPrincipal = new ClaimsPrincipal(identity);

        var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;

        // signs out the current user
        authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);

        // you need this for the current request, otherwise user will be authenticated only for the next request.
        HttpContext.Current.User = claimsPrincipal; 

        // sets the cookie for the next request
        authenticationManager.SignIn(new AuthenticationProperties(), identity);
    }
}

You need to apply this attribute to controllers/actions where you'd like to authenticate users with the token.

Give this a bash. I'm not absolutely sure it will work from the first attempt - this is adapted version of what I have.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.