custom authorization in oAuth 2 - filter

I am creating a web application in asp.net mvc and I have the Api's for the same
now I have multiple users in my data base like below
AdminUser
GeneralUser 1
GeneralUser 2
AdminUser and GeneralUser 1 logged in my system and the token is generated using oAuth Token.
Token for AdminUser is (bbhights)
Token for GeneralUser 1 is (klkokoiu)
ideally my token should get validated with the particular user like the token which is generated by AdminUser should be worked only for that particular user and the same should be happened with all the general users
but when I hit my Api with the Id of AdminUser and the token of GeneralUser 1 user the data is being fetched from the Api's
I am using [Authorize] attribute in every api call but only token is getting authorize and it is not checking the user to which the particular token is assigned
as I have very less knowledge about the oAuth2 tokens I am not able to understand what should I do
should I create a override method to validate user and token?
but the problem is I am concerned about the existing functionality of the token varification attribute, can I use the below class in my application
public class CustomAuthAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
}
}
and there are total 3 different methods in AuthorizeAttribute class named as below
OnAuthorization
HandleUnauthorizedRequest
IsAuthorized
what should I use alongside OnAuthorization method
or should I create some custom filter to validate my token with userId?

Related

Update the authorities in the Authentication object once the user is authenticated and before authorizing him for an endpoint

I have a situation where i have to authorize the user to certain path (endpoint) depending on the role he has.
Problem: Once the user is authenticated, i see an empty set of authorities in authentication object (which is used by authorizing filter to determine access for the user.)
I am new to spring security and would need help to address this.
Background: We have a authorization server implemented in the organization which uses oauth2 and lets us do the single sign on. SSO happens in the front end which gets the token from the authorization server and embeds it to every request sent to my server. Now my server decodes the token and authenticates the user. the user claim doesn't have authorities information and i am not allowed to make any code changes in my authorization server..
What i am looking for : Once the user gets authenticated and before he proceeds for authorization (i am using filters in my web security config) i want to make a call to the DB and get the user respective roles and save it to my authentication object, so that the authorities are now updated, user will be authorized to the endpoint.
You can create a SecurityService and call it from #PreAuthorize annotation
#GetMapping()
#PreAuthorize("securityService.hasRole('ADMIN', authentication.principal.username)")
public String getData() {
return "response";
}
And call authorized server from SecurityService with rest template for example:
public class SecurityService {
public boolean hasRole(String role, String username) {
String role = restTemplate.getRoleByUserName...;
// check role
return false/true
}
}

Update fields of the principal at the runtime

I use OAuth2 authentication with my own authorization and resource server in Spring Boot. I want to change some fields in my User implements UserDetails(it's my Principal) object at runtime on behalf of the same user or on behalf of another user(administrator/moderator). E.g. user1 with id=1 want to change his country, so he calls this method:
#PostMapping("/setMyCountry")
public void setMyCountry(#CurrentUser User user, #RequestParam String newCountry){
user.setCountry(newCountry);
userRepository.save(user);
}
But when I want to check his country using this:
#GetMapping("/getMyCountry")
public String getMyCountry(#CurrentUser User user){
return user.getCountry();
}
I get the same old country.
Similarly, with the changes as administrator:
#PostMapping("/setUserCountry")
public void setUserCountry(#CurrentUser Moderator moderator, #RequestParam String newCountry){
User user = userRepository.findById(1L).get();
user.setCountry(newCountry);
userRepository.save(user);
}
#GetMapping("/getUserCountry")
public String getUserCountry(#CurrentUser Moderator moderator){
User user = userRepository.findById(1L).get();
return user.getCountry();
}
It returns the same country. But, of course, the DB shows new value.
I already saw question about the similar issues, but if I use this in setMyCountry():
Authentication newAuth = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(newAuth);
then this still doesn't work. Please note, that I use my custom tokens, token providers and token granters, but they all return UsernamePasswordAuthenticationToken at the end.
So, how can I change field of the User and update current principal without log out and log in?
Common practice when using oauth2 is that the Authentication server knows nothing about the users, more than user name, password, what roles, and an some sort of key so it can look up the user object. This can be a unique UUID, or the username (subject) as in an email address.
The resource server gets a token from a client, it takes this token and then calls the authorization server to verify the token, the authorization server verifies it and if verified then sends back information to the resource server so that the resource server can populate its UserDetails object.
If the resource server needs to know say what country this user lives in, it gets the id from the Principal/UserDetails object and then calls maybe a user service, or another database, or another table, or even back to the authorization server that maybe has a /user endpoint and presents the token to the authorization server (that in turn gets the principal info, gets the subject and then looks up in a database for the user info) and then send the user object back.
What my point is that you should always separate Authentication and Authorization (roles etc) information, from the actual User information.
What if you change from say using facebook authentication to github authentication. Do you need to redo all the users? no, because you have all user information separated from the authorization information.

ServiceStack Jwt authentication check if authenticated

I need to allow anonym access endpoint but still check if user is authenticated then give some extra data.
using [Authenticate] attribute I can use
var session = SessionAs<AuthUserSession>();
and then session.IsAuthenticated
it works just fine but without [Authenticated] attribute session is empty(new session is generated with new id and all props is not populated with user data)
How to check if user is authenticated without [Authenticate] attibute with request which uses jwt token?
The JwtAuthProvider is an IAuthWithRequest provider which only validates the JWT Token and returns the appropriate HTTP Error Response if the token is invalid when it needs to Authenticate the the Request, e.g. when Services annotated with the [Authenticate] attribute. If Services don't require Authentication, the IAuthWithRequest Auth Providers and JWT Bearer Tokens aren't validated and the Users Session isn't automatically populated.
But in the latest v4.5.9 that's now on MyGet new APIs have been added to JWT AuthProvider to be able to create custom JWT Tokens and convert them into User Sessions, specifically you can create a UserSession from a JWT Token with:
var session = JwtAuthProvider.CreateSessionFromJwt(base.Request);
Which is just a helper for resolving the registered JwtAuthProviderReader and calling its ConvertJwtToSession() API:
var jwtProvider = (JwtAuthProviderReader)
AuthenticateService.GetAuthProvider(JwtAuthProviderReader.Name);
var session = jwtProvider.ConvertJwtToSession(base.Request, base.Request.GetJwtToken());

Role-based authorization in ASP.NET Web API - how to set roles on the principal?

I am using recipe 10-3 in the newly released book ASP.NET Web Api 2 Recipes to support basic authentication in my Web API. This recipe utilizes a 3rd party library from Thinktecture. As seen from the below code, I am authentication the user against my own account service.
using Thinktecture.IdentityModel.WebApi.Authentication.Handler;
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
var authenticationConfiguration = new AuthenticationConfiguration();
var accountService = ServiceLocator.Get<AccountService>();
authenticationConfiguration.AddBasicAuthentication((userName, password) => accountService.Authenticate(userName, password));
config.MessageHandlers.Add(new AuthenticationHandler(authenticationConfiguration));
...
}
}
Now I want to make role-based authorization in my controllers using the Authorize attribute:
[Authorize(Roles="administrator")]
public IHttpActionResult Get()
{
...
}
My account service obviously knows about the users and their assigned roles, but this information is not available to the Authorize attibute (the roles are not set on the principal).
How do I accomplish this? Can the Thinktecture authentication handler be configured to set the roles on the principal? Or should I make my own custom Authorize attribute (deriving from the Authorize attribute)? And if so, should I override the OnAuthorization method to create and set the principal using my account service? Or maybe override the IsAuthorized method directly? Or maybe something else...
The AuthenticationHandler only does authentication. You'd need to set the roles in a separate step (e.g. in a delegating handler).
If you are on Web API v2 - I'd rather recommend switching to the basic auth OWIN middleware
https://github.com/thinktecture/Thinktecture.IdentityModel/tree/master/source/Thinktecture.IdentityModel.Owin.BasicAuthentication
This gives you full control over the principal that gets created.
https://github.com/thinktecture/Thinktecture.IdentityModel/blob/master/samples/OWIN/AuthenticationTansformation/KatanaAuthentication/Startup.cs
There is also a nuget.
I found out that the AddBasicAutentication method actually has an overload that takes a delegate for providing the roles. This is exactly what I was looking for. So now the call to AddBasicAuthentication looks like this, and everything works like a charm:
authenticationConfiguration.AddBasicAuthentication((userName, password) => accountService.Authenticate(userName, password), (username) => accountService.GetRoles(username));

Using AuthorizeAttribute in ASP.NET Web API

I have used the [Authorize] attribute in an ASP.NET Web API method
[Authorize]
public IEnumerable<User> GetAllUsers()
From the application I can access this method without a problem as my user is already authenticated. However, is there any way that I can specify the username, password to this method when calling so that I can implement a REST API? This is when calling from a standalone application or the browser.
I didn't entirely understand your question but System.Web.Http.AuthorizeAttribute checks against Thread.CurrentPrincipal to see if the user is authorized or not.
You can specifically give user permissions if you want as below:
[Authorize(Users = "User1")]
public IEnumerable<User> GetAllUsers()
But the Authentication process is entirely up to you. I would recommend authenticating the user through a message handler and then populating the Thread.CurrentPrincipal there. Then, use the AuthorizeAttribute as you see fit for your application.

Resources