Simple token-like authentication - php

Does the following authentication system seem reasonable:
Client calls the login end point with a user name and password to the main server. The main server sends this off to another authentication server (which will receive no further mention), which returns a yes/no if this is valid and a user ID that the main server is aware of. If yes, generate a random token (using some crypto library that spits out random strings), and store the hash of this (using PHP's password_hash()) and an expiry 12 hours from now on the user record. Return the token to the client.
Client now adds "Authorization: Token TOKEN+HERE+ABCD1234" to their requests to other endpoints. The server ensures that the hash of the token in the auth header matches the one in the database (using salts through PHP's password_verify()), and that the expiry hasn't been hit. If it doesn't match, or the expiry is exceeded, then send back a 401.
Seems at least as secure as basic HTTP authentication, which just has the base-64 encoded user:password in the header? The reason I'm considering this scheme over basic is that the main server won't store the username/password that the authentication server is using to log in.
What am I forgetting? Is this grossly insecure?

Your scheme is not that different from the standard server-side sessions where SESSION-ID is normally nothing more than a random token and stored on the client side within a cookie, with 2 improvements:
Instead of a cookie you would use Authorization header to deliver the token. This acts as a CSRF protection.
You would hash a token on the server-side. This helps against session hijacking in case someone gets access to your token-store on the server-side.

If you see the oAuth process of Google then you will get idea of how Authorization works for them.
They have different servers for Authorization and API calls. User sends authentication details to Authorization server and receive a code. Google is having process of taking user consent to access details but you can skip this process to take consent and just return code on successful details.
This code can be further used to get the Access Token from the API server. So your first request to API server would be to get the Access Token. Google is having facility to refresh your Access Token as well.
And all subsequent request to API server must contain Access Token. So you seems to be missing this Code exchange process to make it more secure.
More info: https://developers.google.com/identity/protocols/OAuth2

Related

Is it necessary to use a JWT token when logging in to Angular 6 and PHP web app

About the login step at Angular 6:
If I did it as the following:
Send username and password to PHP;
Server code check user if exists;
If really exists, we will send a json array again to Angular containing username and user role
Save them in localstorage
And when user try to navigate through the app, we will check these credentials using canActivate guard service.
Do we need to use JWT too to set a token or isn't necessary ?
Its not compulsory to use JWT, If your application requires extra
mission critical security use it.
Using JWT protects data from unwanted modifications before its received by the server. The unwanted modifications may be made by someone intercepting the data or from the user itself .
JWT just sends data to server in encoded format along with signature. So, that modification become little tough or even if made, data is not accepted by server as signature validation fails.
Sample JWT data passed :
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 // header
.eyJrZXkiOiJ2YWwiLCJpYXQiOjE0MjI2MDU0NDV9 // payload
.eUiabuiKv-8PYk2AkGY4Fb5KMZeorYBLw261JPQD5lM
Sample plain/json data
{
"username": "hello",
"full_name" : "Jason Bourne"
}
Here, you can easily see and modify the data passed, and in JWT you can't.
Yes! you need, because :
The token-based authentication systems allow users to enter their username and password in order to obtain a token which allows them to fetch a specific resource - without entering their username and password at each request. Once their token has been obtained, the user can use the token to access specific resources for a set time period.
JWT (pronounced 'jot') is a token based authentication system. It is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature. The JWT is a self-contained token which has authentication information, expire time information, and other user defined claims digitally signed.
Source: JWT (JSON Web Tokens) Are Better Than Session Cookies
more info: JWT
introduction: this link
Implementation example: php-authorization-jwt-json-web-tokens
It is not neccessary, but may come in handy.
If you have single application working on a single webserver you could skip JWT completely and just have a cookie autentication mechanism, so that each JavaScript call to the webserver contains your authentication cookie so your backend can respond with proper user data.
JWT comes in handy though when you have more servers involved. Think of SSO service acting as a glue between multiple related sites, like StackOverflow and others. You just pass the JWT token and each server can safely assume the data was not tampered with and have immediate access to the user's identity, some basic details etc.

JWT token login and logout

Hi I am creating mobile native application that uses REST API endpoints to communicate with server side.
I have had previous experience developing native clients, but I have simple token (random generated string) stored in DB in the same table where user information is stored. So it is like sessions used in browser, but instead of cookies each request has token in the header.
Recently I discoreved JWT token. It seems to be great way to secure endpoints which are private. You can request token from mobile client providing you pass + login and get generated token in response.
But the one important thing is that this token is not stored anywhere on the server, server verifies the token using secret word, which is private for the server like private key.
That's okay for secured endpoints, but what to do if I require user session, for example how do apps like Facebook, Amazon, Aliexpress ... work, they have ability to use the app without providing credentials, just navigating through the store, but require logining in when user want't to make purchase. And after that user session is kept for some time.
This can be implemented with the JWT token without any problems, but when user need to logout, what to do in this case ? Token is not stored anywhere on the server, so how can I destroy this token, to make it invalid ?
If token is stored in the database, API is not stateless, as REST API should be.
So in general there is no way to keep user logged in in stateless API, am I right ?
I have some ideas how to implement this using JWT token, but again this will not be stateless API, as I understand.
Create the list of expired tokens
Store JWT token in the database, but what is the purpose of self descriptive token (JWT) in this case if it is stored in the database, the main idea of JWT token to keep all information with token, as I know.
Please suggest what is the best way will be in this case, and correct me if I have mistaken.
Thanks.
If you're using JWTs, then you can't have a server side state in order to properly logout the user without defeating the purpose of using JWTs in the first place. The best option though if you want to do this is to have a last logout date stored in the DB and in the JWT, and if these don't match you logout the user (without updating the date in this case). However, you now have server side state.
Storing logged out tokens in the DB seems like overkill though.
An alternative option is that you could generate a 128 bit token generated by a CSPRNG, store this using SHA-256 in the database, and then use the unhashed value in a web token. This way you can simply delete the entry in order to logout the user server side. This is the more secure option as you now have a way to properly expire tokens and sessions on the server. If a user changes their password, or wants to secure their account by logging out other sessions you now have a way to do this.
JWT authentication is basically happens on both the client side and server side.
When the user sends Username and password to authenticate. its checked against the db and if valid a joken is generated and sent back to the user. There are multipe API's for generating the JWT token, you can check out http://jwt.io/
Once the token is generated and sent back, it needs to be sent along with header in each request and needs to be validated, on the server side, before serving the API back to the user.
There is no need to store the the token as the API itself will allow you to decode it on the server side.
How i am doing it:
I generate a random id (I call it validation code) and store it in database when user signup, encode it in jwt.
Whenever any request is made with jwt, I check the validation code, if it is correct: access is granted.
To expire the session like after changing password, I change the validation code in DB.
If you need to logout a user, provide a logout link. The server should reset the session data by encoding the token with any empty array for example. The user will have a valid session but will not have the valid information to validated them.
Valid Token at login
$data = array("id"=>1,"user_type"=>"Admin");
$token = JWT:encode($data, $key);
Validating Token
$token = $_POST['token'];
$data = JWT:decode($data, $key, $hash);
if($data.id){
return "valid token";
}else{
return "invalid token"
}

Token authentication - where to store the token

I am working with PHP and Laravel at the moment, I have a restful api that the user needs to authenticate with to make sure they can only access things they own etc.
What I want to know is where should the token from the server be saved on the client? In a session a cookie? The servers database?
I suggest to go the following route:
the user logs into your site and requests a API usage token
when a new request to your API comes in, compare the token from the incomming request, with the token in the db. if it is found, it's a valid request. the REST client could use the Authorization header to send the token.
send the answer for the request
While the login system of your website, might be session-based with cookies on client-side, the REST API is token-based and doesn't need a cookie or session.
Please take a look at this for more details:
https://softwareengineering.stackexchange.com/a/141434/111803

OAuth and Cookies

I am currently implementing an OAuth authentication 3 legged strategy using 2.0. I have come across a problem:
What's the best way to remember the client's session when logging in using Oauth.
Currently what I'm doing is setting a cookie on the client that matches my session ID on the server. This is of course equivalent to a normal cookie session based login. Then in the session, I keep track of the access token that I got when I used the Auth Code and exchanged it for the access token.
As you can see, state is kept in sync between the client and the server via the cookie/session id, and the access token is kept only in the server and in relationship to the session id.
However I've read that this is insecure, and that OAuth should be stateless (restful) style, so cookies should not be required, especially if the client is a machine client and not a browser client. Some resources have mentioned that the client should store all the necessary credentials in order to authenticate any request to the app. Does this mean I should store the access token in the browser's header? What about the auth code from the redirect, should this be stored on the browser's header as well? (And should these codes/tokens be encrypted/signed on the browser's headers) (and how would you do this using PHP?)
Resources like this: http://sitr.us/2011/08/26/cookies-are-bad-for-you.html says a client side rich javascript app could keep track of the access token and pass it in on every XHR request? But of course not every client is a javascript app such as machine clients.
You should not store the token in a regular session.
The idea of it being stateless is that each request carries all the required validation information.
Of course this may require more work on the client side in order to ensure all requests carry all the required data.
One of the benefits of REST's statelessness is that it is simpler to have a distributed implementation. Every request has all the necessary data so you don't even need to hit the same server twice, each server can validate on its own.

OAuth2.0 Server stack how to use state to prevent CSRF? for draft2.0 v20

I am using PHP library for OAuth2.0 v20
In draft20, there is a mention of the use of state to prevent CSRF
So far, my own web app that implements this PHP library allows the following:
3 legged authentication using Authorization Code Request
2 legged authentication using Resource Owner Credentials Grant
a Request that refreshes an access token
Do I need to use state for all of the 3 situations above?
If so, what is a good example of "state"?
what makes a good "state"?
Any ideal length? Any minimum length? Any maximum length?
Any ideal makeup? alphanumeric including upper case?
It might be helpful to step through an example CSRF exploit in order to understand how a state parameter mitigates such an attack. In this example Mallory is the attacker and Alice is the victim.
The Attack
Mallory visits some client's website and starts the process of authorizing that client to access some service provider using OAuth
The client asks the service provider for permission to request access on Mallory's behalf, which is granted
Mallory is redirected to the service provider's website, where she would normally enter her username/password in order to authorize access
Instead, Mallory traps/prevents this request and saves its URL
Now, Mallory somehow gets Alice to visit that URL. If Alice is logged-in to the service provider with her own account, then her credentials will be used to issue an authorization code
The authorization code is exchanged for an access token
Now Mallory's account on the client is authorized to access Alice's account on the service provider
So, how do we prevent this using the state parameter?
Prevention
The client should create a value that is somehow based on the original user's account (a hash of the user's session key, for example). It doesn't matter what it is as long as it's unique and generated using some private, unguessable information about the original user.
This value is passed to the service provider in the redirect from step three above
Now, when Mallory gets Alice to visit the saved URL (step five above), that URL includes the state parameter generated with Mallory's session information
The authorization code is issued and sent back to the client in Alice's session along with Mallory's state parameter
The client generates a new state value based on Alice's session information and compares it to the state value that was sent back from the authorization request to the service provider. This value does not match the state parameter on the request, because that state value was generated based on Mallory's session information, so it is rejected.
An attacker should not be able to generate a state value for any specific user and, therefore, tricking a user into visiting their authorization URL has no effect.
Just for #1 -- 3-legged authorization using Authorization Code flow.
When your application exchanges the authorization code for an access token, you want to be sure that the OAuth flow which resulted in the authorization code provided was actually initiated by the legitimate user. So, before the client application kicks off the OAuth flow by redirecting the user to the provider, the client application creates a random state value and typically store it in a server-side session. Then, as the user completes the OAuth flow, you check to make sure state value matches the value stored in the user's server-side session-- as that indicates the user had initiated the OAuth flow.
A state value should typically be a pseudo-random unguessable value. A simple value can be generated as an int with the rand() function in PHP, though you could get more complex as well to provide greater assurance.
The state exists to prevent things like me sending you a link via e-mail which contains an authorization code for my account, you clicking on it and the application pushing all the data into my account unbeknownst to you.
Some additional information is in the OAuth 2.0 threat model document:
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-threatmodel-00
In particular, see the section on CSRF protection:
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26#section-10.12
As the "state" is just a random string, making something like this should do the trick:
$state = md5(uniqid(rand(), TRUE));
Just remember to save it in your session so you can check it later on.

Categories