Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically login local user after registration with IdentityServer3

Using IdentityServer3 I need to automatically login and redirect a local user back to the client application after the user has completed a registration process. Is there an elegant way to do this? From my digging I suspect not, in which case is there a hack I can use to achieve this?

I was able to achieve this for external users using a custom User Service, but this utilized a partial login. However, for local users they aren't in the authentication process handled by the User Service until they login with a username and password.

Please also note that I don't have access to the users password as the registration process is covered by multiple screens / views as in this instance they are required to verify their email as part of the registration process.

Progress:

I've found this https://github.com/IdentityServer/IdentityServer3/issues/563 but haven't worked out how to trigger the redirect.

I'm attempting to issue an authentication token using:

var localAuthResult = userService.AuthenticateLocalAsync(user);
Request.GetOwinContext().Authentication.SignIn(new ClaimsIdentity(localAuthResult.Result.User.Claims, Thinktecture.IdentityServer.Core.Constants.PrimaryAuthenticationType));

But the best I can do so far is redirect the user back to the login screen:

HttpCookie cookie = Request.Cookies["signin"]; // Stored previously at beginning of registration process
return Redirect("~/core/login?signin=" + cookie.Value);
like image 583
Gavin Avatar asked May 14 '15 02:05

Gavin


1 Answers

Add the registration link to the login page using LoginPageLinks:

var authOptions = new Thinktecture.IdentityServer.Core.Configuration.AuthenticationOptions
{
    IdentityProviders = ConfigureIdentityProviders,
    EnableLocalLogin = true,
    EnablePostSignOutAutoRedirect = true,
    LoginPageLinks = new LoginPageLink[] { 
        new LoginPageLink{
            Text = "Register",
            Href = "Register"
        }
    }
};

Using LoginPageLinks will result in a signin url parameter will be added to the end of your url on the login page. This needs to be preserved if the registration process spans multiple pages. Easy to store this value in a cookie.

A gotcha is that the registration page must exist under the same url as Identity Server, e.g. "core". This will allow your pages to share cookies with Identity Server. In standard MVC controllers this can be achieved using the Route decorator:

[Route("core/Register")]
[HttpGet]
[AllowAnonymous]
public ActionResult Register(string signin)
{
    Response.Cookies.Add(new HttpCookie("signin", signin)); // Preserve the signin so we can use it to automatically redirect user after registration process
    return View(new RegisterViewModel());
}

Once the registration process has been completed you can use the IssueLoginCookie extension method to create a login cookie. The signin url parameter can then be used with the GetSignInMessage extension method to retrive a ReturnUrl to redirect the response to which will automatically login the user and return them to the client application:

using Thinktecture.IdentityServer.Core.Extensions;
using Thinktecture.IdentityServer.Core.Models;

...

AuthenticatedLogin login = new AuthenticatedLogin()
    {   
        IdentityProvider = Thinktecture.IdentityServer.Core.Constants.BuiltInIdentityProvider,
        Subject = userId,
        Name = AuthObjects.AuthUserService.GetDisplayNameForAccount(userId)  
    };
Request.GetOwinContext().Environment.IssueLoginCookie(login);

HttpCookie cookie = Request.Cookies["signin"];
if (cookie != null)
{
    SignInMessage message = Request.GetOwinContext().Environment.GetSignInMessage(cookie.Value);
    return Redirect(message.ReturnUrl);
}
else

...
like image 172
Gavin Avatar answered Nov 01 '22 08:11

Gavin