symfony2 security - disable login path and show forbidden - ajax

i am trying to prevent redirect to login page when user is trying to access a page without token, i have single page app and i am only putting the ajax requests under firewall and when a user is doing ajax without token i want the ajax to return forbidden exception so i will be able to catch it in client side
currently the ajax returns "Found" since the request is being redirected to the login page
i haven't found a solution in cookbook so far i dont want to use api tokens, only send an exception instead of redirecting to login

You need to define an entry_point to your firewall in order for you to return unauthorized response. Information about entry points can be found in the documentation here. I will copy the paragraph in case of future requests here.
When the user is not authenticated at all (i.e. when the token storage has no token yet), the firewall's entry point will be called to "start" the authentication process. An entry point should implement AuthenticationEntryPointInterface, which has only one method: start(). This method receives the current Request object and the exception by which the exception listener was triggered. The method should return a Response object. This could be, for instance, the page containing the login form or, in the case of Basic HTTP authentication, a response with a WWW-Authenticate header, which will prompt the user to supply their username and password.
So in order for you to do that, you have to create a class that is going to be defined as a service.
It should look like this:
namespace MyBundle\Service;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
class CustomEntryPoint implements AuthenticationEntryPointInterface
{
public function start(Request $request, AuthenticationException $authException = null)
{
$response = new Response("", Response::HTTP_UNAUTHORIZED);
return $response;
}
}
And in your services.yml file
services:
service.entry_point:
class: MyBundle\Service\CustomEntryPoint
And finally pass the service id service.entry_point to your entry_point option in firewall section of security.yml file.
This should do the trick.

Related

How to access JWT in Quarkus when proactive auth is disabled?

I need to access a jwt sent in authorization header. I also have to disable the proactive auth check. How can I get the token?
I have this class which used to work when proactive auth was enabled:
#RequestScoped
public class AccessRights {
#Inject
JsonWebToken accessToken;
public boolean validateAccess() {
if(accessToken.getRawToken() == null)
throw new AccessDeniedException("Invalid Access Token");
JsonObject claim = accessToken.getClaim("claim");
// ... do some validation ...
}
}
When I set quarkus.http.auth.proactive=false it stops working. The accessToken is always null. Now that is expected since its documented here https://quarkus.io/guides/security-jwt#proactive-authentication and here https://quarkus.io/guides/security-built-in-authentication#proactive-authentication. I tried to use the alternative way suggested in the docs, but I cannot get it to run.
Problem: I don't know how to get a JsonWebToken from the suggested workaround
Problem: Even when I try to use securityIdentity instead, it is always null. Plus I don't know yet how to actually use it for validation.
#RequestScoped
public class AccessRights {
#Inject
CurrentIdentityAssociation currentIdentityAssociation;
public boolean validateAccess() {
SecurityIdentity identity = identities.getDeferredIdentity().await().indefinitely();
// identity is always null
}
}
EDIT:
To add more context: I have a graphQL API and the initial problem was, that if I receive an expired token, the framework will respond with a 401 unauthorized error. However as is best practice in graphQL, I need to respond with a 200 with json body that describes the error. The proactive auth check prevents the graphql error handler to kick in. That is why I disabled it, effectively making things worse.
Here is how the whole auth process in my application works:
The API receives a request that should contain a bearer token (JWT) in the authorization header. The token is acquired somewhere else. My application needs to validate the issuer and expiration time. This part used to be handled by the pro-active auth check. After that my custom validateAccess() method will extract some roles from the token. If those roles are not present, I will call an external api, providing the raw token, to get back some more detailed access rights.
I believe you missed something important here.
Docs says that :
By default, Quarkus does what we call proactive authentication. This means that if an incoming request has a credential then that request will always be authenticated (even if the target page does not require authentication).
Which implicitly means : if you disable proactive auth, you need to require auth to be done before accessing resource.
That may be part of your problem, as you disabled proactive auth, you'll have to explicitly restrict access to resources to authenticated clients. Otherwise, no auth is performed and thus SecurityIdentity is null.
If you already tried that, please add more code and context. I'll gladly edit my response.
EDIT 1 :
I see 2 distinct problems in informations you added :
You got to validate token (if proactive auth is disabled)
You got to get response code 200 with error details instead of 401
But as you clearly stated, token validation works out of the box with proactive enabled.
So, I would suggest you to let proactive auth do its job. Then, I would add an ExceptionMapper.
This way, you can write custom code for Exception unfolding, and you can respond what you want for every situation.
See ExceptionMappers documentation for more

How to resolve unauthenticated issue in Postman GET Request

I used Laravel-8 for rest api. The route is shown below:
localhost:8888/myapp/server/api/v1/admin/role
It is a GET Request.
When I send it on POSTMAN, I got this error:
401Unauthorized
{
"message": "Unauthenticated."
}
In my route I have:
'middleware' => ['auth:api']]
The reason is because I don't know how to add the Login details. email: akwetey#gmail.com, password: mypass
How do I achieve this?
Thanks
This person walks you through the process nicely and should get you setup.
https://coding-lesson.com/api-authentication-with-laravel-passport/
Basically you need to:
Get to your login api, probably something like: localhost:8888/myapp/server/api/v1/login
Create a POST request to the login API, select the Body tab and define key values for you Email and Password
Then run the request and copy the AccessToken value from the results
Now with your API above, select the Authorization tab, choose Bearer Token as the Type and paste in your AccessToken value for the Token field
You should also go to your Headers table and define Accept and Content-Type keys, both with values of: application/json
Of course you'll want to then change all this to use variables after you get it right, so you don't have to keep repeating this with all your new API calls.
To fetch data behind protected routes you need to provide a token that will verify that the user who made the call is authenticated.
Then you have to provide the token in Authorization section of postman.
I assume you know the difference between Post and Get. Laravel works a little different then regular PHP, let me tell you how.
In order to access the protected routes you'll have to first access the token from login route. By sending the required data in .
Once that's done it'll return the token which can be used to access the protected routes under admin or auth middleware.
In your case you're accessing localhost:8888/myapp/server/api/v1/admin/role which is a protected route under admin middleware. You'll have to first access token and then send token with the get request to fetch the required data.

Spring Security loginPage Vs loginProcessingURL

what is the difference between loginPage vs loginProcessingURL.
.formLogin().loginPage("/login").usernameParameter("phone-number").passwordParameter("password")
Seems to be loginProcessingURL is like post method once user submits the data in the login page but when I remove also it is working fine. What is the significance of loginProcessingURL and how does it differ from loginPage?
The line loginPage("/login") instructs Spring Security
when authentication is required, redirect the browser to /login
we are in charge of rendering the login page when /login is requested
when authentication attempt fails, redirect the browser to
/login?error (since we have not specified otherwise)
we are in charge of rendering a failure page when /login?error is
requested
when we successfully logout, redirect the browser to /login?logout
(since we have not specified otherwise)
we are in charge of rendering a logout confirmation page when
/login?logout is requested
AND
.loginProcessingUrl("/login/process")
tells Spring Security to process the submitted credentials when sent the specified path and, by default, redirect user back to the page user came from. It will not pass the request to Spring MVC and your controller.
Refer documentation
Purpose of loginPage()
The loginPage() tells the framework where the user will be redirected when login is required. For example when you are not authorized to the page, you get redirected to this page. This page performs the login activity, for example when you implement a loginForm() or oauth2Login() like in my code using Google OAuth2,this page redirects to google login.
http.anonymous().and()
.authorizeRequests().antMatchers("/images**").permitAll().and()
.authorizeRequests().anyRequest().authenticated().and()
.oauth2Login()
.successHandler((request, response, authentication) -> {
request.authenticate(response);
})
.loginPage("/oauth2/authorization/google")
.loginProcessingUrl("/login")
Purpose of loginProcessingUrl()
The loginProcessingUrl() is the method that automatically set the rule antMatchers("/thisUrl").permitAll() to this URL so that when the response is returned (code, state, token, etc.) will be allowed to be GETed and this response is processed as you can see in the authenticate method of the request. Something more important is that this loginProcessingUrl() tells that the response should be processed to this URL. Without this the request.authenticate(response) will not be executed and authentication will not be returned or otherwise you implement another algorithm.
May the following code segment from spring security source code will help you:
loginPage the login page to redirect to if authentication is required
loginProcessingUrl the URL to validate username and password
DEFAULT_LOGIN_PAGE_URL = "/login"
/**
* Updates the default values for authentication.
*
* #throws Exception
*/
protected final void updateAuthenticationDefaults() {
if (loginProcessingUrl == null) {
loginProcessingUrl(loginPage);
}
//...
}

Check if user is authenticated in laravel API route

So I know API routes are not supposed to rely on sessions authentication, but my idea was to create some API routes, that could be used if needs be by third-party with proper authentication, but that could also be used internally, ie called to get the data I need for my web pages.
I changed the LoginController so that every time a user logs in, a Personal Access token is generated and stored in the database. When logging out, this token is deleted.
So as not to expose the token to the client side, I would like to use a middleware, that would detect, on an API call, if the request comes from a user who is already authenticated. If that's the case, I would retrieve the Personal Access token that belongs to the user, attach it to the request, and pass it onto the API.
Browser -- Query site.com/api/myRoute --> Middleware adds user's token to request if Auth::check() -- Pass-on request --> Controller
I've created a dummy API route to see if I can detect whether a user is authenticated, but that doesn't seem to work... I guess because the 'auth' middleware is not included.. however, if I do include it, I get redirected to home on every request...
Route::get('/test', function() {
if(Auth::check()) {
dd('Hello logged-in');
} else {
dd('Hello not logged-in');
}
});
Any lead on how to achieve that much appreciated!

Laravel 5.3 Ajax Login Customize Credentials

I am able to login via Ajax in Laravel 5.3
This is easily accomplished by making a post request to the login route with the proper parameters.
However, for my application, I am designing two ways for a user to be logged in - via the traditional email/password combination that Laravel already supports, and via an access code that would be distributed and allow the possessor of said code to login without an email/password combination. There is no "registration" in my app, there is just different levels of authentication.
Anyway, in /vendor/laravel/framework/src/Illuminate/Foundation/Auth I am editing the AuthenticatesUsers.php and understand that this function specifically handles the login attempts:
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->has('remember')
);
}
My question is, how can I change the success of attempt() based on the content of the request?
In other words, if someone is sending an ajax access code it shouldn't be tested against an email/password combination, as it would obviously fail. Similarly, if they are sending an ajax with email/password parameters, it shouldn't be tested against the list of available access codes.
Am I on the right track? Where in Laravel can I go to make the Auth::attempt() contingent on request parameters?
I will not advice to edit a framework file.
You should rather write a middleware to handle identification of the type of authentication user is requesting for, before sending it to the controller. In your middleware,
public function handle($request, Closure $next)
{
// check if the request has access_code
$request->attributes->add(['using_access_code' => $request->has('access_code')]);
return $next($request);
}
And in your controller, you can check for positive test on this request parameter that we newly added (you can of course do this inside controller directly, but I personally like middleware to handle this because there are chances that you may want to add more functionality)
In your controller, if using_access_code is false, proceed with attempt() login, else, retrieve the user using access_code and manually authenticate the user using Auth::login($user). Let me know if you are unclear.

Resources