Greeting everyone, I try to configure simple authorization code flow via Spring Security OAuth.
I tested my authorisation and resource server configuration via following approaches:
Create a web application as client and use its page to fire http post call to /oauth/authorize.
After getting code, I use the same page to
fire another http post with code and get token.
At the end, I use
curl -H to place token inside header and get response from protected
resource.
But when I try to use rest template. It throw error message 401 Unauthorised error.
Server side - security configure:
<http auto-config="true" pattern="/protected/**"
authentication-manager-ref="authenticationManager">
<custom-filter ref="resourceFilter" before="PRE_AUTH_FILTER" />
<csrf disabled="true" />
</http>
<http auto-config="true">
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login default-target-url="/admin.html" />
<logout logout-success-url="/welcome.html" logout-url="/logout"/>
<csrf disabled="true" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="admin" password="123456" authorities="ROLE_USER,ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
Server side - authorisation and resource configure:
<oauth:authorization-server
client-details-service-ref="clientDetails" error-page="error">
<oauth:authorization-code />
</oauth:authorization-server>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="admin" secret="fooSecret" />
</oauth:client-details-service>
<oauth:resource-server id="resourceFilter" />
Client Side:
<oauth:client id="oauth2ClientContextFilter" />
<oauth:resource id="sso" client-id="admin"
access-token-uri="http://localhost:8080/tough/oauth/token"
user-authorization-uri="http://localhost:8080/tough/oauth/authorize"
use-current-uri="true" client-secret="secret"
client-authentication-scheme="header" type="authorization_code"
scope="trust" />
<oauth:rest-template id="template" resource="sso"/>
If anyone knows where goes wrong, please do let me know.
There were two issues with my configuration above.
I noticed my client used wrong secret to communicate with authorization server.
Token endpoint at authorization server use authentication manager which
serve user authentication. It result
client are rejected all times until I create new security realm for
token endpoint and configure it to use a authentication manger designed for
client.
Note client is different from user. Client is third party want to access resource belong to your user (also called resource owner).
I had the same problem. It helped to add a
org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService
to spring securities authentication-manager, glueing the clientDetailsService to the authentication manager. So
<authentication-manager alias="authenticationManager">
...
<authentication-provider user-service-ref="clientDetailsUserDetailsService"/>
...
</authentication-manager>
nearly solved the problem for me. I had one more Issue: Since ClientDetailsUserDetailsService has no default constructor, spring threw Exceptions of the form
org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class
[class org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService]:
Common causes of this problem include using a final class or a non-visible class;
nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
Which I could not solve without using a copy of that class receiving the clientDetailsService as property instead of a constructor arg.
Related
I created remember-me in spring-security and also button in front end, but cookie is not getting created.
my spring security.xml
<logout success-handler-ref="logoutSuccessHandler" />
<remember-me key="_spring_security_remember_me"
user-service-ref="userDetailsService" />
How to manipulate session in spring mvc . I have searched in the network and I found that Spring MVCcould be the solution. But the problem is I can only pass two parameters of authentification (the username and the password)
<user-service>
<user name="user" password="123456" authorities="ROLE_USER" />
</user-service>`
and in my case I must pass three parameters.I would be so grateful if I found the solution in this forum.
I'm fresh off the boat to Spring Security so excuse me if this seems awfully trivial..
I try to put the Spring Security mechanism in my MVC project, but for some reason the access-denied-handler doesn't send my unauthorized user to the denied access page and instead chooses to present the login page.
Here is my Http tag in the security-context.xml:
<http authentication-manager-ref="dao-auth"
access-decision-manager-ref="accessDecisionManager"
disable-url-rewriting="true">
<intercept-url pattern="/pages/home.html" access="USER"></intercept-url>
<intercept-url pattern="/home" method="GET" access="USER"></intercept-url>
<intercept-url pattern="/logout" access="USER"></intercept-url>
<intercept-url pattern="/denied" access="ROLE_ANONYMOUS"></intercept-url>
<intercept-url pattern="/error" access="ROLE_ANONYMOUS,USER"></intercept-url>
<intercept-url pattern="/" access="ROLE_ANONYMOUS,USER"></intercept-url>
<intercept-url pattern="/pages/**" access="ROLE_ANONYMOUS,USER"></intercept-url>
<intercept-url pattern="/resources/**" access="ROLE_ANONYMOUS,USER"></intercept-url>
<form-login login-page="/login" authentication-failure-url="/denied"
default-target-url="/home" />
<logout invalidate-session="true" logout-success-url="/"
logout-url="/logout" />
<access-denied-handler error-page="/denied" />
<session-management invalid-session-url="/login">
<concurrency-control max-sessions="1"
expired-url="/login" />
</session-management>
</http>
Basically the way I test it is I try to access the /home path from the ROLE_ANONYMOUS user and instead get thrown to the /login one.
Also, can't figure out how to debug this thing or where I find the logs (feels like there are somewhere out there..)
Thanks to all responders :)
1.Spring security looks for Authentication object in security context first. If there is no authentication object (basically a principal) found in the security context, it will direct you to the login page.
2.If it finds Authentication object, then it will use the principal's authorities to do authorization.
3.When Login screen is presented, the user entered credentials are authenticated and if not authenticated, then you can throw a bad credentials exception to show the access denied error.
I'm making a Spring MVC web-app with some RESTfull resources as an API.
I need the RESTfull part to have some custom filters as I do not want any redirection and I want any exception to be translated with the corresponding HTTP error code and a basic JSON description.
On the other hand, the rest of the website have to be more common and redirect people when they are not logged in etc.
One more thing, I wish to use the #Secured annotations and a post-authentication in some case.
How do I define the multiple http namespaces correctly (on Spring 3.1)?
Here is my erroneous configuration:
<global-method-security secured-annotations="enabled" />
<http pattern="/rest/**" authentication-manager-ref="authenticationManager" entry-point-ref="restAuthenticationEntryPoint">
<form-login login-page="/rest/login" login-processing-url="/rest/postlogin"
authentication-success-handler-ref="restAuthenticationSuccessHandler"
authentication-failure-handler-ref="restAuthenticationFailureHandler"
username-parameter="username" password-parameter="password" />
<logout logout-url="/rest/logout" invalidate-session="true" />
</http>
<http pattern="/**" authentication-manager-ref="authenticationManager">
<form-login login-page="/login" login-processing-url="/postlogin"
username-parameter="username" password-parameter="password" />
<logout />
</http>
The funny part is that this configuration works partially as I can login with /rest/login and I get the response from my custom success handler. I can also login from /login and I get the proper redirection to /. The logout are working both fine too.
Next, all the controllers beans have #Secured("ROLE_USER") in the secured methods. But all the secured methods don't ever get secured. Why is that so?
#Secured({"ROLE_USER"})
#RequestMapping(method = RequestMethod.GET, headers = { "Range" })
public #ResponseBody
HttpEntity<List<T>> list(#RequestHeader("Range") String range) {
I've read documentations everywhere and I'm more confused than ever.
Why are my methods not being secured?
Must the http namespace define an access so that the #Secured annotations work?
Are the http namespace overwriting my #Secured annotations? If it's so, how can I define multiple "login pages" with custom filters and being able to use annotations?
Here are some facts:
* I'm using Spring and SpringSecurity 3.1
* I have a custom AuthenticationManager to retrieve user details from hibernate daos.
* Some controllers are extending an abstract class where the #Secured annotations lies. But it still doesn't work for a simple controller.
* My controllers are discovered with a context:component-scan and a base-package.
* The security works fine with one http namespace.
please help, i'm getting mad with this!
Check out this answer about making sure the web context is visible to the global-method-security declaration and possibly using class proxying.
To answer your other questions, no the http namespace shouldn't affect the use of #Secured annotations, other than that the user is authenticated by the web part of the application and that information will be used by the method security interceptor when making an access decision. Unless you override it (using access-decision-manager-ref), method security will use a standard AccessDecisionManager which grants or denies access based on the roles a user has.
In my web app users are able to change their user details. The URL for this page is:
springproject/usermanagement/edituserinfo/4
where "4" is the user id.
My security-context looks like:
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/usermanagement" access="isAuthenticated()" />
<security:intercept-url pattern="/usermanagement/new" access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/usermanagement/edit/*" access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/usermanagement/edituserinfo/*" access="isAuthenticated()" />
</security:http>
How can I restrict the user only to access their own "edituserinfo" page? E.g. user with user id 1 can only access: "springproject/usermanagement/edituserinfo/1 " and not "springproject/usermanagement/edituserinfo/4 "
You can also accomplish this using Spring Security's #PreAuthorize which supports expressions:
#PreAuthorize("#userId == principal.id")
public void doSomething(#PathVariable String userId);
See the Spring docs:
Access Control using #PreAuthorize and #PostAuthorize
Use a PathVariable on the URL, like #RequestMapping("/usermanagement/edituserinfo/{userid}") and in your code validate the logged-in user's Spring Security context principle (via SecurityContextHolder.getContext().getAuthentication().getPrincipal()) against the userid path variable. If they don't match, bounce the user out, log a SecurityException, and send an email to the admins.