0
votes

This authentication normally just involves calling the '/Token' endpoint, with user credentials, and receiving a ticket back containing an auth token for the user. I am calling this in my Web API from a WPF client application, and it would make life much easier for me, and the login process much quicker, if I could simple have one authentication request that returns the authenticated IdentityUser, or in a normal template based API project, an AspNetUser object.

I see the method TokenEndPoint in my API's ApplicationOAuthProvider does very little, so I don't think a change there could help much, but the GrantResourceOwnerCredentials seems to be the crux of that provider, yet its return is void.

The options for the provider include:

AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin")

but I can find no evidence of that action being executed. I trace all successful requests to a log, and my Debug.WriteLine($"API TRACE: ExternalLogin called for {provider}.") doesn't appear in the output window, so I don't think I can use that action to server redirect to one that returns a User.

Is there anything I can do, except call the /Token endpoint from a login action that allows anonymous, and then redirect?

EDIT: The method that grants the token is in the ApplicationOAuthProvider class provided in my project template. It derives from OAuthAuthorizationServerProvider. It is:

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    var userManager = context.OwinContext.GetUserManager<UserManager>();
    var user = await userManager.FindAsync(context.UserName, context.Password);
    if (user == null)
    {
        context.SetError("invalid_grant", $"The user name or password is incorrect.");
        return;
    }
    ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
        OAuthDefaults.AuthenticationType);
    ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
        CookieAuthenticationDefaults.AuthenticationType);
    AuthenticationProperties properties = CreateProperties(user.UserName);
    AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
    context.Validated(ticket);
    context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
1
I'm not sure what you want. Do you need windows authentication so not token is required? Then look at asp.net/web-api/overview/security/…. Otherwise, what do you want that makes it easier than requesting a token based on credentials and pass that token in every request in a header? What would you gain?Peter Bons
@PeterBons No, none of that. When the token is granted, see my edit above, the user requesting it is also signed in. I would like to get that user back in the same response I get the token back. I think the question subject hints at that, and the text makes an effort to explain it.ProfK

1 Answers

0
votes

It is possible to do a Server.Transfer within the GrantResourceOwnerCredentials method of the ApplicationOAuthProvider : OAuthAuthorizationServerProvider class. This is provided out-the-box in the either the project template or a Nuget package.

The transfer would be to an added Login method in the AccountController, with username, password, and an additional ticket parameter, which will return an AspNetUser user class, to which you can add an extra property for the authentication ticket obtained in GrantResourceOwnerCredentials and normally returned by the /Token resource.

But this is too much meddling in code not written by me, so for this urgent prototype of the project, I just call /Token, and when I have the username, I call /User to get the now signed in AspNetUser.