5

I have WebApi application and added UserID to token in ApplicationOAuthProvider class:

    public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
        foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
        {
            context.AdditionalResponseParameters.Add(property.Key, property.Value);
        }

        context.AdditionalResponseParameters.Add("ID", context.Identity.GetUserId<int>());

        return Task.FromResult<object>(null);
    }

Now how can I get this ID in my controller method?

I try the following:

[Authorize]
public class ApiEditorialController : ApiController
{

    public HttpResponseMessage GetEditorialRequests()
    {
        int id = HttpContext.Current.User.Identity.GetUserId<int>();

        var r = Request.CreateResponse(HttpStatusCode.Accepted);
        r.ReasonPhrase = "Cool!";
        return r;
    }

}

But I get NullReferenceException on

int id = HttpContext.Current.User.Identity.GetUserId<int>(); 

string....

UPDATE: Look at the Response below (from Francis Ducharme) just override OnAuthorization instead on create private contructor :)

public class AuthorizeApiFilter : AuthorizeAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        string token = string.Empty;
        AuthenticationTicket ticket;

        token = (actionContext.Request.Headers.Any(x => x.Key == "Authorization")) ? actionContext.Request.Headers.Where(x => x.Key == "Authorization").FirstOrDefault().Value.SingleOrDefault().Replace("Bearer ", "") : "";

        if (token == string.Empty)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Missing 'Authorization' header. Access denied.");
            return;
        }

        //your OAuth startup class may be called something else...
        ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(token);

        if (ticket == null)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid token decrypted.");
            return;
        }

        // you could perform some logic on the ticket here...

        // you will be able to retrieve the ticket in all controllers by querying properties and looking for "Ticket"... 
        actionContext.Request.Properties.Add(new KeyValuePair<string, object>("Ticket", ticket));
        base.OnAuthorization(actionContext);
    }
}

Thank you, Francis Ducharme

1
  • very strange, I have called the project today and it works... Commented Mar 7, 2016 at 20:46

2 Answers 2

6

You could, in GrantResourceOwnerCredentials of your OAuth startup class, add it there to the dictionary.

ticket.Properties.Dictionary.Add(KeyValuePair<string, string>("UserID", user.Id.ToString())); //the user object from your authentication logic...

Then Implement an AuthorizeAttribute in which you can retrieve the token that was sent in the Authorize header of the request, unprotect it and add it to the request properties that will then be available in all controllers' methods.

public class AuthFilter : AuthorizeAttribute
{
    private void AuthorizeRequest(HttpActionContext actionContext)
    {
        string token = string.Empty;
        AuthenticationTicket ticket;

        token = (actionContext.Request.Headers.Any(x => x.Key == "Authorization")) ? actionContext.Request.Headers.Where(x => x.Key == "Authorization").FirstOrDefault().Value.SingleOrDefault().Replace("Bearer ", "") : "";

        if (token == string.Empty)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Missing 'Authorization' header. Access denied.");
            return;
        }

        //your OAuth startup class may be called something else...
        ticket = Startup.OAuthBearerOptions.AccessTokenFormat.Unprotect(token);

        if (ticket == null)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid token decrypted.");
            return;
        }

        // you could perform some logic on the ticket here...

        // you will be able to retrieve the ticket in all controllers by querying properties and looking for "Ticket"... 
        actionContext.Request.Properties.Add(new KeyValuePair<string, object>("Ticket", ticket));
    }
}

Then in your web methods, Request.Properties will contain Ticket, which itself has a dictionary with the UserID.

You need to register the AuthorizeAttribute in WebApiConfig.cs

config.Filters.Add(new AuthFilter());
// I also have this in my Web API config. Not sure if I had to add this manually or the default project had these lines already...
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
Sign up to request clarification or add additional context in comments.

7 Comments

I get An exception of type 'System.Collections.Generic.KeyNotFoundException' occurred in mscorlib.dll but was not handled in user code Additional information: The given key was not present in the dictionary. when I try to call var ticket = Request.Properties["Ticket"];
very strange, code of AuthFilter is never called, although I have registered it in WebApiConfig.cs...
the same :( AuthFilter.AuthorizeRequest is never called
@OlegSh Since I made you register it globally, try removing the [Authorize] attribute on your web method.
Of course I removed. PS. Very strange, but standard userID = HttpContext.Current.User.Identity.GetUserId<int>(); works now
|
0

You need to intercept the response message and attach that value back to your user.

The AdditionalResponseParameters will show up in the response, but your application won't assign them to anything unless you tell it to.

Locate the code that you use to assign claim values / name etc to your users (on the redirect back to your site from the OAuth provider), and then look for the parameter on the respones there.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.