JSF 2 and the Basic HTTP authentication - jsf-2

We have an web app what uses Basic HTTP authentication.
web.xml
...
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>file</realm-name>
</login-config>
...
Indirect usage somewhere in the deep code space ...
User getLogedUser(HttpServletRequest request)
And I have to rewrite it in JSF 2, but I have no clue how can use the this authentication method in JSF 2. (i could not find the way how can i get 'HttpServletRequest request')
Google did not throw any useful hit on his first page
Thanks for the answers in advance.

The raw HttpServletRequest is in JSF available by ExternalContext#getRequest().
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest request = (HttpServletRequest) ec.getRequest();
// ...
However, I think it's better to change the getLoggedUser() method to take the remote user instead.
User getLoggedUser(String remoteUser)
so that you can just feed either ExternalContext#getRemoteUser() or HttpServletRequest#getRemoteUser() to it. This also decouples the method from any Servlet API or JSF API dependency.

I guess you are looking for ExternalContext.getRemoteUser()
which returns the user name.
Usage:
FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();

Related

Configure the landing page after SSO authentication

I want to know how to setup the relay state with the new saml library. Basically once I am authenticated via the asserting party, I want to have a relay state url (a JSP in my application), where I should land. In the saml extensions library, as far as I know, the relay state url was set in the SAMLMessageContext object.
Actual Behaviour The mechanism of setting the page where I would be redirected to after SAML login has changed. I am not sure how to set the desired JSP where I want to land in the new library.
Expected behavior After the successful call to the assertionConsumerServiceLocation in my application, I should be taken to a Url configured by me (Relaystate). I need help in configuring this URL.
I tried to set up the relay state like this :-
Saml2AuthenticationRequestResolver authenticationRequestResolver(
RelyingPartyRegistrationResolver registrations) {
OpenSaml4AuthenticationRequestResolver authenticationRequests =
new OpenSaml4AuthenticationRequestResolver(registrations);
authenticationRequests.setRelayStateResolver(relayStateResolver);
return authenticationRequests;
}
I have defined the relayStateResolver like the following :-
private Converter<HttpServletRequest, String> relayStateResolver = (request) -> "my_desired_jsp_url_string";
Are my above configurations correct, and would they help me in landing on the desired JSP page after successful login?
Currently, below is the error I am facing with the above implementation. I am working to fix that (I need to get the Opensaml4 from Shibboleth's repository of artifacts), but wanted to know if the above configuration is correct before making that fixing effort.
Jan 03, 2023 5:54:28 AM org.apache.catalina.core.StandardWrapperValve
invoke SEVERE: Servlet.service() for servlet [dispatcher] in context
with path [/company] threw exception [Filter execution threw an
exception] with root cause java.lang.NoSuchMethodError:
org.opensaml.saml.saml2.core.AuthnRequest.setIssueInstant(Ljava/time/Instant;)V
at
org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver.lambda$resolve$1(OpenSaml4AuthenticationRequestResolver.java:60)
at
org.springframework.security.saml2.provider.service.web.authentication.OpenSamlAuthenticationRequestResolver.resolve(OpenSamlAuthenticationRequestResolver.java:133)
at
org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver.resolve(OpenSaml4AuthenticationRequestResolver.java:59)
at
org.springframework.security.saml2.provider.service.web.Saml2WebSsoAuthenticationRequestFilter.doFilterInternal(Saml2WebSsoAuthenticationRequestFilter.java:184)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
Because RelayState can be used for several things and is not always used to describe the post-login redirect URL (the spec says MAY), it is not defaulted to do this.
You can configure Spring Security to redirect to the RelayState parameter by configuring a SimpleUrlAuthenticationSuccessHandler like so:
#Bean
public SecurityFilterChain appEndpoints(HttpSecurity http) {
SimpleUrlAuthenticationSuccessHandler successHandler =
new SimpleUrlAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter(Saml2ParameterNames.RELAY_STATE);
http
.saml2Login((saml2) -> saml2
.authenticationSuccessHandler(successHandler)
// ...
)
// ...
return http.build();
}
You will also need to configure the relay state resolver, as you have already shown in your post.

#WithMockKeycloakAuth get accesstoken as bearer String for mockMvc perform Header

I have one service and Keycloak 11 as Authentication server. Now I want to write tests. To mock the accesstoken, I use #WithMockKeycloakAuth. This works well and I get an unauthorized when I pass a bad role for example. Now I want to document it with spring rest docs the therefor I have to add the acesstoken as header field ( Bearer tokenAsBearerString ). Because of the annotation, the mocked token is added to the SecurityContext and I can extract it before doing the mvc.perform.
#Test
#Order(5)
#WithMockKeycloakAuth(authorities = "ROLE_owner")
void createProduct_RealmRoleOwner_HttpStatusCreated() throws Exception {
SecurityContext context = SecurityContextHolder.getContext();
KeycloakAuthenticationToken authentication =(KeycloakAuthenticationToken) context.getAuthentication();
AccessToken token = authentication.getAccount().getKeycloakSecurityContext().getToken();
The problem is that I need the accesstoken as Bearer string representation. I'm not yet very familiar with the jwt topic but I expected that if I use the mocked acces token and convert it to a jwt format / Base 64 encoded String the header should be correct.
In addition: I'm running a Keycloak container via docker in a seperate network so it is not reachable while I run my automated test. So mocking would be the only solution.
This question was also asked (and answered) here with a little more context.
The code snippet provided above doesn't show that test class is decorated with #AutoConfigureMockMvc(addFilters = false), reason why the security context is not attached to the MockMvc HTTP request (this is normally done by a spring-security filter).
The complete stack trace isn't provided neither, but it's very likely that the exception occurring when filters are enabled is due to JwtDecoder wiring from Keycloak boot lib. #MockBean JwtDecoder jwtDecoder; should be enough to fix it.
Finally, it is one of main features of the lib #WithMockKeycloakAuth is taken from to skip fetching, decoding and parsing an actual JWT from Keycloak instance. Trying to build an authorization header with valid JWT from mocked spring authentication is ...

How to obtain HttpServletRequest #Context in DropWizard Auth

I am using Basic Auth in Dropwizard 0.8
and I need to get access to the request context in my SimpleAuthenticator class, beyond the basic credentials.
Perhaps I need my own AuthFactory implementation to do this?
I want to implement basic access control for Basic Auth based on the resource path requested.
Thanks
Jon
#PermitAll
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getResponse(**#Context** SecurityContext context) {
SimplePrincipal principal = (SimplePrincipal)context.getUserPrincipal();
return Response.ok("{\"Hello\": \"" + principal.getUsername() + "\"}").build();
}
Using #Context suffice for the basic Authorization atleast for Dropwizard version 0.9.2
I haven't used 0.8, but in 0.9+, you can use #Auth and #PermitAll to control which resources have auth and which ones don't. Would that not satisfy your requirement? or you prefer a finer grained control?
Here's a changeset for auth in 0.9. You can refer to Dropwizard: BasicAuth for sample code.

Return username and password to login form grails spring security

When a user fails authentication, I want the username and password to be returned to the form.
I'm using the spring security core plugin with Grails and Spring Security LDAP. I've searched around for a while and have come up with zip. Any ideas?
From UsernamePasswordAuthenticationFilter javadoc:
If you want to retain the username, cache it in a customized AuthenticationFailureHandler
As for password there is no point to cache it, because it cannot be put back to form password field for security reasons.
For future reference, as the above answers are either too vague to be helpful to those of us who are just beginning to learn this framework for the first time (prompting such questions as: what's an AuthenticationFailureHandler? How do I implement one? How do I connect it to my existing infrastructure that was magically created by the <security:http> namespace handler?) or no longer work (the code to store the username in SPRING_SECURITY_LAST_USERNAME was removed from UsernamePasswordAuthenticationFilter as of version 3.1.0), here's a little more detail on the first answer:
An AuthenticationFailureHandler is used by the login process to decide what to do when authentication fails.
The default login form setup as provided by <security:http><security:form-login /></security:http> uses a SimpleUrlAuthenticationFailureHandler to perform the redirection to the login failed url (which defaults to /spring_security_login?login_error).
You can hook your own implementation in by using the authentication-failure-handler-ref attribute of your <form-login> element.
So, my implementation looks like this:
public class UsernameStoringUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler
{
#Override
public void onAuthenticationFailure (HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
{
request.getSession (true).setAttribute ("SPRING_SECURITY_LAST_USERNAME", request.getParameter ("j_username"));
super.onAuthenticationFailure (request, response, exception);
}
}
which is configured thus:
<security:form-login authentication-failure-handler-ref="authenticationFailureHandler" [...] />
...
<bean id="authenticationFailureHandler" class="my.package.UsernameStoringUrlAuthenticationFailureHandler" p:defaultFailureUrl="/LoginError" />
And then I can access the failed login username using the same approach as described in James Kleeh's answer here, but which no longer worked because of the change to the framework.
I was able to do the following to get the username back to the form: In LoginController.groovy:
render view: view, model: [postUrl: postUrl,
rememberMeParameter: config.rememberMe.parameter,
lastUsername: request.getSession().getAttribute("SPRING_SECURITY_LAST_USERNAME")]

Spring security : Redirect to previous url after logout

I've got a web app that uses spring security. I'm wanting to redirect the user back to the same page they were on before log out when they log out.
Is there an easy way to do this?
Not sure which Spring version this question was referring to - but there is a useReferer property on the standard org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler since Spring 3.0.
So all you need to do is configure it like this and the logout will redirect to wherever the user came from:
<bean id="logoutSuccessHandler" class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler">
<property name="useReferer" value="true"/>
</bean>
<security:http>
<security:logout logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
</security:http>
What you need is a Simple LogoutSuccessHandler
#Component
public class CustomLogoutSuccessHandler extends
SimpleUrlLogoutSuccessHandler implements LogoutSuccessHandler {
#Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse
response, Authentication authentication)
throws IOException, ServletException {
if (authentication != null) {
System.out.println(authentication.getName());
}
response.setStatus(HttpStatus.OK.value());
response.sendRedirect(request.getHeader("referer"));
}
And later call it in your configure method i.e
.logout().logoutSuccessHandler(customLogoutSuccessHandler)
This will redirect you to referer URL.
You can add a new filter in the filter chain of the spring security. That new filter will be applied to the /logout URL. When going trough this filter you can save the current page in a field variable. And when returning through the filter. You can redirect the request to the saved URL. I think this can help. You can get the current page URL by using the Referer header in the Request object.
Just a thought:
How about we keep a stack of visited pages. may be at max 3 entries. and redirects user from logout.
Configure a Filter or extend spring security filter to maintain a stack in session about last two visited URLs
On logout configure a servlet as logout-success-url .
Now get the URL from session stack and now invalidate the session and redirect user to that page
Also you can make use of referrer header as Vijay has mentioned

Resources