#WithMockUser ignores username, password fields? - spring-mvc

I'm using #WithMockUser to test a controller method secured with basic auth in a simple spring boot web service. My annotation looks like:
#WithMockUser(username = 'admin', password = 'mypassword', roles = ['ADMIN'])
It seems however that the username and password field are ignored. The test passes even if I specify an incorrect username or password. The roles field however does appear to be used and the test fails with an invalid role is provided.
Perhaps I'm misunderstanding the role of this annotation, but should I be able to use it to verify behavior of incorrect credentials being supplied to a secured method?
Thanks!
--john

If you are using Spring MVC Test (i.e., MockMvc), you would do something like the following:
mvc.perform(get("/").with(httpBasic("user","password"))) // ...
This is documented in the Testing HTTP Basic Authentication section of the Spring Security reference manual.
If you have configured your test to launch Spring Boot with an embedded Servlet container, you can use Spring Boot's TestRestTemplate which supports "Basic HTTP authentication (with a username and password)".

This has happened to me as well. I think #WithMockUser is enough to test secured services. user/password/roles is not required. I validated this scenario in my case.

Related

Endpoint authorization for service to service call

I have a .net core API with multiple endpoint. I am using Identity Server 4 for authentication. Token will be generated based on correct user name and password.
In the Same API, I want to add another endpoint which should only be accessed by API call only and normal user should not be able to access the end point.
I am thinking of Policy based authorization for the endpoint.
Is it a correct approach?
There's a couple things you could do.
As you mention you can use authorization policies. If you're using OAuth; your source API can use client credential grant type to obtain a M2M token (a.k.a. machine-to-machine token). In the target service can do a check the gty claim is equal to client_credentials, and if not; return HTTP 403 response.
Use the API gateway and only expose public APIs/operations on internal services - don't expose public routes for APIs/operations that should be restricted to service-to-service calls.
Do both #1 and #2.
Yes, you need to configure your policies. For that you need to understand the difference between authentication and authorization, and setup them both. For example in our project we use several different authentication sources, and then map them to authorization policies
services.AddAuthentication()
.AddScheme<...>("scheme1", ...)
.AddScheme<...>("scheme2", ...)
...;
services.AddAuthorization(opts =>
{
opts.AddPolicy("policy1", policy => policy.AddAuthenticationSchemes("scheme1")
.<some other requirements specific to this policy>
.RequireAuthenticatedUser());
opts.AddPolicy("policy2", policy => policy.AddAuthenticationSchemes("scheme2")
.<some other requirements specific to this policy>
.RequireAuthenticatedUser());
}
After which you could just use [Authorize("policy1")] and [Authorize("policy2")]. Or you could make one policy the default by adding
opts.DefaultPolicy = new Microsoft.AspNetCore.Authorization
.AuthorizationPolicyBuilder()
.<requirements go here>
and then use [Authorize] to use the default policy, and [Authorize("policy1")] for special cases.

Spring-Security-OAuth2 - how to add fields to access token request?

I have a Spring Boot application, that is using Spring Security with OAuth 2.0. Currently, it is operating against an Authentication Server based on Spring Example code. However, running our own Auth Server has always been a short-term target to facilitate development, not a long-term goal. We have been using the authorization_code grant type and would like to continue using that, irrespective of the Auth Server implementation.
I am attempting to make changes to use OAuth 2.0 Endpoints in Azure Active Directory, to behave as our Authentication Server. So far, I have a successful call to the /authorize endpoint. But the call to get the /token fails with an invalid request error. I can see the requests going out.
It appears that parameters that Azure states as mandatory are not being populated in the POST request. Looking at the Azure doco, it expects the client_id to be defined in the body of the message posted to the endpoint, and that is not added, by default, by Spring.
Can anyone point me in the right direction for how I can add fields to the Form Map that is used when constructing the Access Token request? I can see where the AccessTokenRequest object is being setup in OAuth2ClientConfiguration....
#Bean
#Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
protected AccessTokenRequest accessTokenRequest(#Value("#{request.parameterMap}")
Map<String, String[]> parameters, #Value("#{request.getAttribute('currentUri')}")
String currentUri) {
DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(parameters);
request.setCurrentUri(currentUri);
return request;
}
Should I be trying to define the map in a request.parameterMap spring property? If so, I'm not too sure how that works.
Or should I be using one of the interfaces defined in the AuthorizationServerConfigurerAdapter class?
I have the information to include when sending the AccessTokenRequest, I just don't know the best way to configure Spring to include it? Thanks for any help.
Actually, I found this out. I needed to change the client authentication scheme. Simply adding the following to my application properties added the client_id to the form....
security.oauth2.client.clientAuthenticationScheme=form
If you're using yaml, then yaml-ize it. Thank you Spring!

Authorization by Role/Group in ASP.NET using Auth0

Thanks in advance for your help in this matter!
I was hoping someone could help me figure out how to authorize API access by Group assigned in the Auth0 Authorization extension.
I currently am using the [Authorize] attribute in the web api perfectly - it allows an api call if they have signed in successfully and blocks it if not.
However, if I try [Authorize(Roles = "myGroupName")] authorization fails. Same occurs if I add it to the users app_metadata manually in the Users dashboard on the Auth0 website instead of assigning through the extension.
My project is set up by following the Angular Quick Start and Asp.Net Quick Start. My webapiconfig where I validate the token server side is:
class WebApiConfig
{
public static void Register(HttpConfiguration configuration)
{
var clientID = WebConfigurationManager.AppSettings["auth0:ClientId"];
var clientSecret = WebConfigurationManager.AppSettings["auth0:ClientSecret"];
configuration.MessageHandlers.Add(new JsonWebTokenValidationHandler()
{
Audience = clientID,
SymmetricKey = clientSecret
});
configuration.Routes.MapHttpRoute("API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
}
}
The Auth0 Authorization extension currently supports authorization decisions through the concept of groups. You can create a group, assign users to that group and that configure an application to only be accessible to user within a specific group. All of this would be handled automatically and any user outside of the application expected groups would be denied complete access.
Your use case is a bit different, but valid nonetheless. You want the groups configured with the extension to be sent along the generated token so that the application itself makes authorization decisions based on those values.
In order for the groups configured within the extension to be sent along in the token, the first thing you need to do is request them. For this, you need to include the groups scope when performing the authentication requests.
Add the user's group membership to the outgoing token (which can be requested via the OpenID groups scope);
(emphasis is mine, source: Authorization Extension Docs, section Rule Behavior)
If you request a token using that scope and then decode it in jwt.io, you would get something similar to this (the actual groups would vary by user):
{
"groups": [
"GROUP-1",
"GROUP-2"
],
"iss": "https://[tenant].auth0.com/"
}
Now, for the validation of this information on the ASP .NET API side. Assuming the sample you're using is this one (ASP.NET Web API), the group information contained within the token would be mapped to the following claims:
Type: groups | Value: GROUP-1
Type: groups | Value: GROUP-2
This happens because of the logic that exists in the JsonWebToken class which handles arrays coming from the JWT payload by creating per-value claim that share the same type.
The final part is making sure the AuthorizeAttribute checks these claims of type groups instead of trying to lookup role claims. You should be able to accomplish this, by changing the RoleClaimType constant in the JsonWebToken class to have the value "groups" instead of "http://schemas.microsoft.com/ws/2008/06/identity/claims/role".
Like you certrainly know, the Authorize attribute works using what is in the principal: something that inherits IPrincipal.
In web api, it is even more specific; it is something that inherits ClaimsPrincipal (this implements himself IPrincipal).
As you certainly know already, a claim is like a key-value pair.
The ClaimsPrincipal contains a serie of key-value pairs that are directly taken from the authentication token. This authentication token is issued by the authentication server most of time as JWT (Json Web Token). Most of time as well, the authentication server is using OAuth, like is your case.
If the user group, that you expect to be the role in your application doesn't work by using the out-of-the-box Authorize attribute, it's because it is not mapped correctly: Auhtorize checks the claim with claim type: http://schemas.microsoft.com/ws/2008/06/identity/claims/role (the "claim type" is the "key" of the key-value pair). That means that if you want your Authorize to work, this claim must be valued with the group.
You can do several things to have a clean authorization in your application.
Make a custom Authorize attribute. This Authorize attribute would check the role using a different claim type. The claim type that refers to the user group depends on your authentication server. If you don't find what claim type is used for groups in the doc of your authentication server, run your application in debug, and check every claim that is contained in the property User of your controller. You will certainly find what the claim type you are interested in.
Change the setup of your authorization server by redefining the mapping between user information and claims of the token that is produced (in your case, map groups of the user to the claim that has the type http://schemas.microsoft.com/ws/2008/06/identity/claims/role). Generally, this can be setup per client application or even globally. For example this is the way that must be done if you use an ADFS authentication, AzureAD or WSO2 authentication server (http://wso2.com/products/identity-server/)
Add an owin middleware to modify the current principal. It will change the current principal by copying the value of the claim that contains groups into the claim type http://schemas.microsoft.com/ws/2008/06/identity/claims/role. This middleware must be inserted in the flow after the authentication middleware
I have no rights to comment so I'm going to inquire from here. Why are you doing this
[Authorize(Roles = "myGroupName")]
as far as I remember when I was implementing group based authorization I was still typing
[Authorize(Roles = "myRoleName")]
Not other way around.

Spring Security with external authentication

I have a working spring security that works againts a local db. Now I'd like to move the authentication part by calling a webservice as follow
RestTemplate rt = new RestTemplate();
boolean valid = rt.getForObject(HostConfig.HOST+"/authenticate?username=hq&password=a123456",Boolean.class);
The above service returns true or false.
I'd like to know on which class I should override the existing authentication with the above. Any ideas?
org.springframework.security.core.userdetails.UserDetailsService is the thing that you are looking for. You should implement the method loadUserByUsername(), and check the password etc.
HTH

Implementing a SAML assertion flow with Spring Oauth2

I need to implement a SAML assertion flow using Spring OAuth2 Authorization Server. I'm struggling with how to tie these two projects up.
I've tried importing the SAML securityContext into my OAuth project as well, however it seems that the SAML flow will always take precedence. Is there a way to do this where it would look at the grant_type to determine if it should use the saml flow.
Also, when it does process the saml assertion, would that tie into the ResourceOwnerPasswordTokenGranter, or would I have to register a custom token granter with something like this?
With OAuth2, we have a way of registering different TokenGranters through something like this:
List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();
tokenGranters.add( endpoints.getTokenGranter());
tokenGranters.add(new SamlTokenGranter(authenticationManager,tks,cds,endpoints.getOAuth2RequestFactory()));
CompositeTokenGranter ctg = new CompositeTokenGranter(tokenGranters);
endpoints.tokenGranter(ctg);
thanks ahead of time for any help you can provide
You might need to register a custom TokenGranter. The CompositeTokenGranter (the default) can handle multiple grant types by doing what you suggest (comparing the incoming requested grant_type to the one supported by each granter). If you are using Spring SAML as a service provider to check the assertion, then I guess you also need to set that up as a separate security filter on the /token endpoint (with a very specific request matcher so it only intercepts SAML grants).

Resources