I'm practicing with asp.net webapi, and want to make separated authorization service.
So I implement authorization service based on tokens (owin), and data provider service. Now I want to override Authorize attribute in data provider service. It must take bearer token from current request, make request to authorization service, receive information about user and his roles.
The question is: how I can get bearer token in my custom attribute, and maybe there are better ways to make this "token transfer"?
I want to use it like this:
//data service
[CustomAttribute (Roles = "admin")]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
public class CustomAttribute : System.Web.Mvc.AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext context)
{
using (WebClient client = new WebClient())
{
string bearerToken;
//somehow get token
client.Headers.Add("Authorization", "Bearer " + bearerToken);
string userinfo = client.DownloadString("authURL/GetUserInfo");
CustomUser user = JsonConvert.DeserializeObject<CustomUser>(userinfo);
if (!user.Roles == this.Roles)
{
//return 401
}
}
}
}
// authorization service
public async Task<UserInfoResponse> GetUserInfo()
{
var owinContext = HttpContext.Current.GetOwinContext();
int userId = owinContext.Authentication.User.Identity.GetUserId<int>();
var response = new UserInfoResponse()
{
UserId = userId.ToString(),
Roles = await UserManager.GetRolesAsync(userId)
};
return response;
}
To answer your specific question about how to access the bearer token in Authorization header of the request:
public class CustomAttribute : System.Web.Mvc.AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext context)
{
System.Net.Http.Headers.AuthenticationHeaderValue authorizationHeader = context.HttpContext.Request.Headers.Authorization;
// Check that the Authorization header is present in the HTTP request and that it is in the
// format of "Authorization: Bearer <token>"
if ((authorizationHeader == null) || (authorizationHeader.Scheme.CompareTo("Bearer") != 0) || (String.IsNullOrEmpty(authorizationHeader.Parameter)))
{
// return HTTP 401 Unauthorized
}
using (WebClient client = new WebClient())
{
client.Headers.Add("Authorization", "Bearer " + authorizationHeader.Parameter);
string userinfo = client.DownloadString("authURL/GetUserInfo");
CustomUser user = JsonConvert.DeserializeObject<CustomUser>(userinfo);
if (!user.Roles == this.Roles)
{
// I recommend return HTTP 403 Forbidden here, not 401. At this point
// the request has been authenticated via the bearer token, but the
// authenticated client does not have sufficient roles to execute the
// request, so they are forbidden from doing so. HTTP 401 Unauthorized
// is a bit of a misnomer because the actual intention is to determine
// whether or not the request is authenticated. HTTP 401 also implies
// that the request should be tried again with credentials, but that
// has already been done!
}
}
}
}
There could be better ways to do what you are trying to do, but I don't know enough about the MVC side of things and the authentication/authorization workflow of your application to be able to provide a good answer to that. At least this should help know where to find the header values from within the authorization attribute.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With