Background: The only experience I have with authentication are normal form-based logins, the typical username, and password to a controller with a redirect or using JWT with a regular login. I would like to use Laravel Passport to achieve the same thing.
I need to create a SAAS app using Vue with Laravel Passport (Laravel 6x with Dingo API).
The app needs to be multi-user with roles and permissions.
I've read that the best methodology is to use the "Authorization Code Grant with PKCE" for a SPA.
The problem that I've run into is that my Vue app sets up the code challenge etc. Requests the authorization code, then gets directed to the Laravel log in page, but as soon as I log in, I get the following screen:
Is there any way to bypass this? (I tried using a custom client with skipsAuthorization, but that doesn't seem to work)
Am I using the correct OAuth flow?
In the Laravel Passport documentation, there are the following:
Password Grant Client: This requires a secret though, so I don't see how I can use this?
Implicit Grant Tokens: This is now discouraged and should not be used.
Which only leaves Personal Access Tokens. But is that the correct "flow" to use?
PKCE should be used according to RFC 8252. I guess a stand alone public SPA can be considered in the same terms as a native app, in that there is no way to store a client secret.
Section 6 requires that both clients and servers use PKCE for public
native app clients. Authorization servers SHOULD reject
authorization requests from native apps that don't use PKCE by
returning an error message, as defined in Section 4.4.1 of PKCE
[RFC7636].
I've read the RFC above and it helped me wrap my head around it. I think the documnetation for PKCE in the Laravel docs are a bit strange (assuming a PHP client for example).
As you said, implicit grant tokens is not recommended anymore (RFC 8252 #8.3):
The OAuth 2.0 implicit grant authorization flow (defined in
Section 4.2 of OAuth 2.0 [RFC6749]) generally works with the practice
of performing the authorization request in the browser and receiving
the authorization response via URI-based inter-app communication.
However, as the implicit flow cannot be protected by PKCE [RFC7636]
(which is required in Section 8.1), the use of the Implicit Flow with
native apps is NOT RECOMMENDED.
I've setup a SPA with a working PKCE-flow. I created a new client model which I then use to skip the dialog you mentioned above.
AuthServiceProvider:
<?php
namespace App\Providers;
use App\Passport\Models\PkceClient;
use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes();
Passport::useClientModel(PkceClient::class);
}
}
App\Passport\Models\PkceClient:
<?php
namespace App\Passport\Models;
use Laravel\Passport\Client as BaseClient;
class PkceClient extends BaseClient
{
public function skipsAuthorization()
{
return $this->firstParty();
}
}
As a sidenote it should be stated that the dialog should not be skipped for clients that is not trusted according to the RFC 8252 8.6
8.6. Client Impersonation
As stated in Section 10.2 of OAuth 2.0 [RFC6749], the authorization
server SHOULD NOT process authorization requests automatically
without user consent or interaction, except when the identity of the
client can be assured. This includes the case where the user has
previously approved an authorization request for a given client id --
unless the identity of the client can be proven, the request SHOULD
be processed as if no previous request had been approved.
Measures such as claimed "https" scheme redirects MAY be accepted
by authorization servers as identity proof. Some operating systems
may offer alternative platform-specific identity features that MAY
be accepted, as appropriate.
Related
I am creating an application with a React front-end and a Java Spring Boot back-end.
My login flow looks like this:
A user clicks on login on the front end
User is redirected to the Google Oauth authorization endpoint on my server
OAuth 2.0 Authorization flow happens: User is redirected to Google and logs in. Google interacts with my server first exchanging an authorization code and then a JWT access token. My server now has the JWT access token for the user.
ISSUE: I now need to redirect the JWT token to my React front-end so that the token can be saved and used every time the user wants to request access to a protected resource on my server.
Is there now an industry standard/best practice for redirecting the token to my React front-end from the server?
There are similar questions on this subject on Stack Overflow, however they are at least 3 years old, e.g. How to provide frontend with JSON web token after server authentication?
Since then the implicit flow has been deprecated, storing JWTs in local storage is no longer recommended, and https://datatracker.ietf.org/doc/html/rfc6750 explicitly discourages passing bearer tokens to the front end in a redirect URL.
I was wondering if anyone knows of an up to date solution for this problem.
There's a draft IETF BCP for OAuth 2.0 for Browser-Based Apps - see here. Basically, it's very similar to native mobile apps using authorization code with PKCE (proof key for code exchange).
FWIW I agree implicit flow shouldn't be used, but IMO you shouldn't be using authorization code flow without PKCE, as this flow is for server side rendered web apps.
EDIT - Auth0 (one of the most popular CIAM solutions on the market) docs say the same thing - see here.
If the Client is a Single-Page App (SPA), an application running in a
browser using a scripting language like JavaScript, there are two
grant options: the Authorization Code Flow with Proof Key for Code
Exchange (PKCE) and the Implicit Flow with Form Post. For most cases,
we recommend using the Authorization Code Flow with PKCE...
Don't.
You seem to mix 2 issues here.
First, you would like to use OIDC for authentication in your SPA. For this you would use OIDC Implicit Flow or Authorization Code Flow with PKCE.
Second, you would like to delegate authentication to google instead of doing it yourself. Basically this is known as federation - you trust external Identity Provider.
The full-blown version would be to setup your own Identity-Provider server (like e.g. keycloak) and configure federation to google there. Your SPA would initiate OIDC against your Identity Provider and wouldn't even know that google did the authentication. You could also easily add further Identity Providers (e.g. facebook) if necessary.
An easier workaround would be to initiate OIDC login from your SPA directly to Google. This way your SPA would receive token directly from google and you would need to protect your own backend as a resource-server accepting and validating those tokens. Adding further Identity-Providers like facebook would be a challenge.
Note that I'm quite new with OAuth2 and OpenID Connect so I may be a little bit confused. AFAIK, the recommanded authentication flow with OAuth2 in 2021 is Authorization Code Flow. I have already read the RFC 6749.
I have initialized a project using JHipster (v6.10.5, not the v7) with this configuration:
Which type of application would you like to create? Monolithic application (recommended for simple projects)
Which type of authentication would you like to use? OAuth 2.0 / OIDC Authentication (stateful, works with Keycloak and Okta)
Which Framework would you like to use for the client? React (i.e. a SPA application)
I'm wondering why is the JHipster's implementation stateful? (i.e. using HTTP session cookie JSESSIONID ; access token and refresh token are stored on the backend-side and NOT on the browser-side).
Why don't they make the browser acting as an OAuth 2.0 client to perform the authentication and storing the access token and the refresh token on the browser-side?
I don't find any explanation on the JHispter security page.
Beside, this blog mentions a schema that explains the OIDC Authorization Code Flow with a Public Client / SPA.
To complete Matt Raible comment, from OAuth 2.0 for Browser-Based Apps - draft-ietf-oauth-browser-based-apps-07 and ยง6.1. Browser-Based Apps that Can Share Data with the Resource Server:
[...]
An additional concern with handling access tokens in a browser is that as of the date of this publication, there is no secure storage mechanism where JavaScript code can keep the access token to be later used in an API request. Using an OAuth flow results in the JavaScript code getting an access token, needing to store it somewhere, and then retrieve it to make an API request.
Instead, a more secure design is to use an HTTP-only cookie between the JavaScript application and API so that the JavaScript code can't access the cookie value itself. Additionally, the SameSite cookie attribute can be used to prevent CSRF attacks, or alternatively, the application and API could be written to use anti-CSRF tokens.
[...]
However, I think the use of HTTP-session and OAuth2 token on the backend-side may complexify the management/implementation of some issues as we have to handle different timeouts:
idle timeout for HTTP session between the browser and the backend
expiration timeout or maximum lifetime expiration for the refresh token that is stored on the backend side
...
I'm now wondering how to provide a user-friendly experience, when some borderline cases happen. E.g: when the refresh token has expired on the backend-side but the end-user is still connected as the HTTP session between the browser and the backend is still valid.
I'm implementing both authentication and authorization mechanisms in Asp.Net Core Web Api application.
I use JWT for users authentication configured in:
ConfigureServices(IServiceCollection services)
{
...
services.AddAuthentication(...).AddJwtBearer(...)
...
}
(similar to https://stackoverflow.com/a/45901894/1544054)
this service also populate HttpContext.User according to the JWT data.
For authorization I use a custom RBAC implementation, based on
class AccessControlFilter : IAuthorizationFilter
{
public AccessControlFilter(string permission) {...}
public void OnAuthorization (AuthorizationFilterContext context){...}
}
(similar to the great answer in https://stackoverflow.com/a/41348219)
I need to know for sure that my AccessControlFilter will run AFTER the JWT Authentication Service, so that the
context.HttpContext.User is already populated.
(I guess that the order is correct and filters will run after services, but I could not find the right documentation.)
From the ASP.NET Core Security Overview (emphasis mine):
Authentication vs. Authorization
Authentication is a process in which a user provides credentials that are then compared to those stored in an operating system, database, app or resource. If they match, users authenticate successfully, and can then perform actions that they're authorized for, during an authorization process. The authorization refers to the process that determines what a user is allowed to do.
Another way to think of authentication is to consider it as a way to enter a space, such as a server, database, app or resource, while authorization is which actions the user can perform to which objects inside that space (server, database, or app).
So to answer your question : authentication always occurs before the authorization pipeline. This makes sense, because you need to know who the user is before knowing what he's authorized to do.
I have a web api application which implements the Resource Owner Password flow from OAuth specification. Everything works correctly.
Actually I configure everything in my WebApiConfig class by using an Authentication filter like this
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add( new HostAuthenticationFilter( OAuthDefaults.AuthenticationType ) );
As some of my customer asked for a different method of authentication I am evaluating to add a couple of features to my services but stil did not have clear how those features can work together.
In particular I cam across a link which explain in very easy words how to implement a HMAC authentication in web api.
Can I implement this authentication method and let the client to choose which one he want to use? Do they can cohesist together?
Yes, your web api service can send back multiple schemes in the WWW-Authenticate challenge. In your case it can send back 'bearer' and 'hmac' for example.
See also this question for more info on using multiple schemes.
BTW, it's not your web api service that supports Resource Owner Password flow. The client uses this flow to get a token from the authorization server that it can use in a bearer scheme with your service (resource server). HTH.
I have an API that requires authentication via OAuth 2.0. I originally anticipated using HWIOAuthBundle, however from investigation this is more to do with hooking up 3rd parties into Symfony's security/auth mechanism and does not provide the required mechanism for validating OAuth 2.0 Authorization headers.
I then found some information about FOSOAuthServerBundle which enables an application to become it's own OAuth 2.0 provider as well as providing the required security mechanisms to validate Authorization headers.
However the problem is that I would like integrate the OAuth 2.0 provider (authorisation server) in an external application (which contains the user base) and not include it within the API. Which will provide some mechanism for performing the token verification against this external app via (another) RESTful API.
Points:
RESTful API requires OAuth 2.0 authentication.
OAuth 2.0 authorisation server to be situated in a separate application.
I feel I should use Implicit grant and call the authorization server on each request to validate that the token is correct.
Is my thinking correct?
As far as I undesratnd your requirement, you require to authenticate your APIs via external OAuth Authorization Server:
Client needs to provide the access token retrieved in the above steps
along with the request to access the protected resource. Access token
will be sent as an authorization parameter in the request header.
Server will authenticate the request based on the token.
If token is valid then client will get an access to protected resource otherwise access is denied.
here is an example which might help you to achieve your requirement. Check this document .
Or simply, you can do with Jersey and Oauth
Also, you can check Apache Oltu and figure out the way to achieve your requirement.
A lot of the big companies like Google, Facebook etc have a separate authorization server from the API server. Check out Google's OAuth authorization flow below
You can also check Google's OAuth Documentation for the details.
So all you would need to do is implement a OAuth Provider so that you can authorize against that provider. There's a list of libraries available on the OAuth website: http://oauth.net/code. You can specifically look here; there is an example for running an OAuth Service Provider in Java.
oAuth can most definitely be a server other than your application server. Below is a picture of what the authentication sequence would look like:
-- Obviously, if the forum can't decode or validate the token, the forum would return a 401 status code instead of a 200 status code.
As long as your oAuth server & the Forum share the same public key, you're more than okay with splitting your oAuth Server & your application.
In fact, take a look at jwt.io. Paste the token you get from the oAuth server into there. It should be able to decode the token right away. Then, you can put your public key into the 'secret' text box to verify the token is verified.
Your application (Forum, in this example) should be able to do the same:
1) Grab the token from the Authorization header of the request
2) Decode the token
3) Check the expire date
4) Verify the token using the oAuth's public key
5) Return successful status code or a failure status code