So, I'm developing an API using slim/slim
and league/oauth2-server
to manage the OAuth2 connection. OAuth2 will be useful because I will need to use Client Credentials grant between services.
Then, I'm also developing an hybrid app with React Native. This app will requires user login by using e-mail and password or connecting with another services (such as Facebook, Google, Twitter, etc).
And I'm confused about what OAuth2 flow to use for this case. Across the web are a lot of articles saying that Resource Owner Password Credentials is not safe anymore, and we should use instead Authentication Code with PKCE.
But I can't discover or understand how to apply Authentication Code with PKCE in a first party app, because all documentation talks about you will need the uses a browser to get authentication code in redirect_uri
.
The flow I imagine is something like that:
- User open the app, then insert your credentials
username
andpassword
; - This screen will connect to API
/request_token
URI sending{ 'grant_type': 'password', 'username': username, 'password': password, 'client_id': CLIENT_ID }
, considering it as a public app we can't sendclient_secret
; - The API validates credentials and returns some data such as
{ "access_token": access_token, "token_type": "JWT", "expires_in": LIFE_SPAN }
, here we will use JWT to gerenate theaccess_token
based inpublic/private key
; - Authentication done, the app will store the
access_token
while it's alive and when it expires will do the flow torefresh_token
.
My question: is it safe? Scott Brady did some "aggressive" article talking it's NEVER safe.
How apps does this things? When I use Instagram app, for example, they own the app and the API, I don't need a browser in the User Experience flow. Are modern apps using "Resource Owner Password Credentials" or "Authentication Code with PKCE"? There is a away to avoid insert browser in the flow while using "Authentication Code with PKCE"?
[EDIT] Possible Solution
As Gary Archer said "Auth Code flow with PKCE is recommended - along with logging on via the system browser", but we are not talking about grant permissions to access users data or third-party apps.
As a designer I don't agree that loggin in the first-party app owned by the same API owner requires a browser this is the not the User Experience we are looking for. And all apps we see such as Instagram, Facebook, Uber... we just put your username and password and we have access to your account.
What I will do is create a custom version of Authentication Code with PKCE removing the required_uri
.
[EDIT:2] The New Flow
After a lot of search, I found some answers I think was interesting to adapt. As above, I removed redirect_url
from flow. Look:
- The flow starts in a login screen, when user give your credentials;
Client generates a
code_verifier
then hashescode_verifier
tocode_challenge
and sends it to Authorization Server with following parameters:response_type=code
: indicates that your server expects to receive an authorization code.client_id=xxxx
: the client id.client_integrity=xxxx
: app integrity check for first-party app.code_challenge=xxxx
: the code challenge generated as previously described.code_challenge_method=S256
: either plain or S256, depending on whether the challenge is the plain verifier string or the SHA256 hash of the string. If this parameter is omitted, the server will assume plain.username=xxxx
: username to authenticate.password=xxxx
: hashed version of password.state=xxxx
: a random string generated by your application (CSRF protection).
Authorization Server will validates user authentication, stores
code_challenge
and return theauthorization_code
with aclient_token
;After receive the
aauthorization_code
andclient_token
, Client saves theclient_token
and immediately sendauthorization_code
back to Authorization Server with following parameters:grant_type=authorization_code
: ndicates the grant type of this token request.code=xxxx
: the client will send the authorization code it obtained.client_id=xxxx
: the client id.code_verifier=xxxx
: the code verifier for the PKCE request, that the client originally generated before the authorization request.
Authorization Server will validates all data and, if everything is right, will return the
access_token
;- Client will set Authorization header with the
access_token
and always sendclient_token
to every request, it will be only accepted with both values are right; - If
access_token
expires, then Client will do a request to refreshaccess_token
and get a new one.
Now, I will reproduce this logic to PHP language. If everything goes right and I hope it does, I will be back with definitive answer.
[EDIT] Clarifications
I'm using OAuth2 to user connect with your third-party accounts (Google, Facebook, etc). But user also can log to a local account in my database. For this case, user doesn't need to grant anything at all. So, no makes sense send user to a browser to him does your login.
I wondering if, to this case, local accounts, we can use Resource Owner Password Credentials or it's more safe Authentication Code with PKCE (we already conclude it's a better approuch). But Authentication Code with PKCE requires redirect_uri
, do I need uses this redirection to log users into a local account where they don't need to grant access?