Customize oauth2 requested scopes - spring-security

My usecase is to customize oauth2 scopes that the user has requested and grant the user only filtered ones,
Eg : User1 wants to generate token, his ldap role is R1 ,and i have a mapping table of R1->read,write
So i want this user to get only the mapped scopes, regardless of the requested scope.
I am trying to add a filter in #EnableWebSecurity class :
#Override
protected void configure(final HttpSecurity httpSecurity) throws Exception {
httpSecurity.addFilterAfter(new OAuth2UsernamePasswordAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class) }
But when i call the /oauth/token API , the attemptAuthentication method is not getting called , it gets called if i put any other api except the /oauth/generate
My OAuth2UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter
.Does any one has a better solution to restrict requested scopes by intercepting the request ?Any help will be appreciated. Thanks

Related

how do I add a 'groups' custom claim to id_token issued by Cognito?

I want to use a custom claim on an open id connect id_token to indicate the groups that the user belongs to.
I have this working with Okta and Spring Security 5. With Okta there was a simple way to set-up a custom claim and associate it with a user's groups.
Now I want to do the same with Cognito.
How do I use Spring Securities group/role authorities in conjunction with Cognito?
I have open id connect login working with Spring Security 5, Webflux & Cognito but now I want to add some role based, group membership coarse-grained entitlements.
I have added a custom attribute to my user-pool but can't see how to populate it.
thanks
Just want to add an implementation example here.
I use my custom JwtAuthenticationConverter to extract cognito:groups and bind them to Spring Security Authorities.
Stack is the same as yours (Webflux, Spring 5 [boot]). Here is the converter class:
#Component
public class GrantedAuthoritiesExtractor extends JwtAuthenticationConverter {
#Override
protected Collection<GrantedAuthority> extractAuthorities(Jwt jwt) {
val authorities = (Collection<String>) jwt.getClaims().get("cognito:groups");
if (authorities == null) {
return emptyList();
}
return authorities.stream()
.map(SimpleGrantedAuthority::new)
.collect(toList());
}
}
And here is the related part in my SecurityConfiguration:
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http,
GrantedAuthoritiesExtractor extractor) {
http
// ...
// Other configurations
// ...
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(new ReactiveJwtAuthenticationConverterAdapter(extractor));
return http.build();
}
Also one point that should be mentioned is that #EnableReactiveMethodSecurity annotation should be placed above SecurityConfiguration class to enable functionality of #PreAuthorize annotations across the application.
I have created another user pool and confirm that adding a custom attribute to the Cognito user pool with the name of 'groups', that is mutable, has resulted in the id_token returned from an openid scope call having a cognito:groups custom claim containing strings representing the groups that the user is allocated to. If the user isn't allocated to any groups then the claim doesn't appear on the token. I suspect this is why I believed it to not be initially working. I couldn't find any explicit documentation that said this his how it works thought. Hope this helps someone, cheers.

Access UserDetails Object inside AuthenticationFailureHandler Spring Security 4.x

I’m migrating an application from Spring Security 3 to 4. The applications utilizes both form based username/password and smart card authentication. It also has a custom AuthenticationFailureHandler that redirects the user to a particular page based on what type of error occurred and the roles associated to the user. For example a locked exception should be handled differently for internal vs external users.
In Spring Security 3 the org.springframework.security.authentication.AccountStatusUserDetailsChecker used to place the UserDetails object into the extraInformation property of the AuthenticationException it threw. The custom AuthenticationFailureHandler we have utilized that to extract the roles from the user who failed authentication so it could handle the different user types appropriately:
#Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
User user = (User)exception.getExtraInformation();
if(exception instanceof LockedException){
if(user.hasAnyRole(Role.INTERNAL)){
//Send to internal user page
}else{
//Send to external user page
}
}
}
However now with Spring Security 4, I’m not sure the best way to get the information about the user into the failure handler so I can appropriately route the request. What would be considered the ‘best practice’ approach for this?
One approach is to extract the relevant information from the request (Either the form based username or the X509 cert) and then look up the roles using a database query but since that is already handled earlier in the Spring Security chain it seems like duplicating that effort in the failure handler isn’t the best approach.
Thanks

Login user at startup

public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
FormsAuthentication.SetAuthCookie(1.ToString(), true);
}
}
An exception of type 'System.Web.HttpException' occurred in
System.Web.dll but was not handled in user code
Additional information: Request is not available in this context
How else can I automatically login a user without having to do a whole new page request?
What part is confusing you? Forms Auth requires a request in order to work. Part of what it does is send a cookie to the client, and it can't very well do that if there's no client. Application_Start runs outside of the request, so you can't access the request object from there. Even if you could, this isn't run for each request, so it would only work for the first user that caused it to activate.
If you want to do this in a global way, but within the request scope, you'll need to use something like a custom action filter or a custom membership provider. Not sure which would be best for something like or even if an action filter would work, but that's your options.

Add roles to ADFS IPrincipal

I have been looking for answer to this question for a few days now, but I have not found any success. I would post the links, but it would probably take up the entire page.
So here is what I have...
I have an MVC application, which uses the WC-Federation protocol. I have been able to configure the application, so that it authenticates the users, and returns the claims from ADFS. This works perfect. I can also extract all the claims with no issues. But I am doing this within one of the actions in the controller.
And here is what I want to do...
I want to use ADFS to authenticate the user, but I want to use my own internal roles to authorize the user to have access to specific controllers (e.g. [Authorize(Roles = "CoolRole")]). I want to be able to do this, because I already have a Web API that uses OAuth 2.0, with a backend SQL Server database to manage users and roles (internal and external user.) I now want a secure portal that will allow internal users to access the data with a single-sign-on experience. Looking at the Controller model, I noticed there are some properties associated with the authentication process (OnAuthentication, OnAuthenticationChallenge) and one for the authorization process (OnAuthorization.)
I don't necessarily need the code, but I feel like I've hit a brick all, and I need to be pointed in the right direction.
UPDATE
I tried this:
protected override void OnAuthorization(
System.Web.Mvc.AuthorizationContext filterContext)
{
//Private class to create a new IPrincipal based on my AppUserMgr
var user = _setCurrentUser(
(ClaimsIdentity)filterContext.HttpContext.User.Identity);
filterContext.HttpContext.User = user;
base.OnAuthorization(filterContext);
}
This returned a 401 (Unauthorized) response.
and...
protected override void OnAuthentication(
System.Web.Mvc.Filters.AuthenticationContext filterContext)
{
//Private class to create a new IPrincipal based on my AppUserMgr
var user = _setCurrentUser(
(ClaimsIdentity)filterContext.HttpContext.User.Identity);
filterContext.Principal = user;
base.OnAuthorization(filterContext);
}
This just calls the STS numerous times, before it fails. I even tried swapping after the assignment to after the base is called in both. No luck.
Prior to the previous ones, I also tried to add an AuthorizeFilter to the control, but that didn't help:
http://pratapreddypilaka.blogspot.in/2012/03/custom-filters-in-mvc-authorization.html
I found this link: http://brockallen.com/2013/01/17/adding-custom-roles-to-windows-roles-in-asp-net-using-claims/
From there, I guessed my way through
Here is the basics of what I did:
I ended up overriding the OnAuthentication method of the Controller, but still made sure to call the base. I did this from within an extended class. Here is the concept:
public class AdfsController : Controller
{
//Some code for adding the AppUserManager (used Unity)
protected override void OnAuthentication(
System.Web.Mvc.Filters.AuthenticationContext filterContext)
{
base.OnAuthentication(filterContext);
//Private method to set the Principal
_setCurrentUser(filterContext.Principal);
}
private void _setCurrentUser(IPrincipal principal)
{
//Put code to find to use your ApplicationUserManager or
//dbContext. roles is a string array
foreach(var role in roles)
{
((ClaimsIdentity)((ClaimsPrincipal)principal).Identity)
.AddClaim(new Claim(ClaimTypes.Role, role));
}
}
}
In the Controller, you can now add the follow:
public class HomeController : AdfsController
{
//I used a magic string for demo, but store these in my globals class
[Authorize(Roles = "CoolRole")]
public ActionResult Index()
{
return View();
}
}
I tested this by checking a role assigned to the current user, and that worked! Then I changed the role to something like "reject", which the user was not assigned; and I received a 401 Unauthorized.
ADFS is the authentication/token service in Azure. to enable the Roles Based Authentication, you can use Azure RBAC (Role Based Access Controll) service to basically Augment the claims that you get back from the ADFS and add the roles that you get back from RBAC to the token, and use the same token in your API so lock down or secure the backend with that augmented token...
here is the reference for RBAC:
http://azure.microsoft.com/en-in/documentation/articles/role-based-access-control-configure/

Authenticate Users However I want

I'm look at Web API 2 with a project that I created as a "proof of concept". I'm trying to see where I inject my own code for customer authentication. I have an internal auth/login service that I would like to call to determine if login credentials are valid and then get user values (id, roles, etc) if it was valid.
I created the project with "Individual Accounts" as the authentication type but I'm having a hard time figuring out where I'm going to call my service and then map the result to an IdentityUser (or some IUser) object.
In the generated ApplicationOAuthProvider class there is code that passes username and password from a context object like so:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
using (UserManager<IdentityUser> userManager = _userManagerFactory())
{
IdentityUser user = await userManager.FindAsync(context.UserName, context.Password);
// ...
How do I hook into that call?
You should do this:
Create your own HTTP Message Handler to authenticate the user. You can put your custom code there. This will execute every request, then you can set the credential in the pipeline of the execution.
HTTP Message Handlers
Create or use the default filters to handle the Authorization
Authentication and Authorization in ASP.NET Web API

Resources