Password protecting certain endpoints/resources - php

I'm building a REST API for part of a folder/file browser application.
One of the aspects of the design is the ability to password protect a folder and I'm just wondering what the best practise would be for this.
My folders table has an is_protected boolean and a password field which will be stored encrypted. This is optional protection.
The developer would send a GET request to http://my-website/api/v1/folders/1 and the backend returns the resource as JSON.
However, if the folder is password protected, I need to check if the password matches. Is it best to maybe send this in the HTTP Header? Or a session using the unique folder slug as the key or something?
All suggestions welcome, cheers!

Your REST API should create a login service, which will take a username / password, and respond with an Authorization token to be used on subsequent requests.. Authorization: token 98wuun8EIU23H8D3D87dow7dh this token should also have an expiry date at which point will need to be refreshed, your app should not pass Username / password on the resource request itself.
The auth token itself should be unique to every user, and on refresh should generate a completely new unique token. Then your token can be used to identify the user on the backend.
refreshing can be done by a refresh token, or by asking the user to enter their username / password again and requesting a new Auth token..
Also ensure your production environment uses SSL to reduce man-in-the-middle type of attacks.

Related

Local Storage with RESTful API for user authentication. Is this a safe method?

I would really like some opinions on whether the following is a safe method as user authentication, and if not, please point out it's shortcomings.
React front end
PHP / MySQL based RESTful API on remote server
1) user signs up, data is posted to the API, user is emailed a single use activation link to ensure email is valid before they can access their account.
2) user signs in, API validates the data in all of the usual ways and then sends back a JSON object containing their user ID and an access token.
3) user ID and access token are set in localStorage on the users device upon receiving the data. React then grabs that data from localStorage and uses it to set and control the state in Redux stores providing an App wide Auth state.
4) user ID and access token are sent along with every future request made to the API. In the instances where a user isn't logged in, i.e - they don't supply a valid user id with matching token, they are automatically prevented from requesting anything that requires authentication at the very first entry point of the API. Suitable responses are sent back which in turn update the front end state to reflect a non-logged in user.
5) When the user logs out the access Token is deleted from localStorage.
A bit more detail about some the inner workings :
All tokens are generated server side and stored in the DB, they are random and unique bin2hex(random_bytes(32)) and only valid when supplied with the matching user ID. So changing the user ID in a request will result in a failed auth response, as will supplying a valid user ID with a mismatching or expired token.
Tokens are single use and a new token is generated, stored and then sent back in the response from every authenticated request along with the corresponding user ID. This may be overkill and put a lot of extra strain on the server. Would really like your opinions on this aspect especially please.
Tokens are set to expire in 2hrs regardless. So if the user leaves themselves logged in, they will be automatically logged out after 2hrs of inactivity.
User ID and Token are sent as part of the JSON body of every request (not in the headers). Is this a cause for concern?
At no point (other than sign up and login) is the users password transmitted or stored in localStorage or used by the React frontend. A matching user ID and Token is all that is required to validate the user after the initial authorization.
All connections are made via HTTPS.
Can you spot any glaring security risks in this approach? Am I missing the elephant in the room here?
Obviously the user ID and matching token is as good as supplying the users email and password on every request as far as auth goes, but I can't use PHP sessions or cookies* as the API is hosted on a different domain. This is the best workaround I could come up with without having to go down the JWT or Oauth route.
How flawed it could be in regards to how I am checking and validating data on the API can't be practically addressed here, but assuming that it is all being done correctly is this method secure enough in principle?
I look forward to and thank you in advance for your opinions :)
*without a ton of workarounds which would ultimately be superflous as this App can only be used with modern browsers which all support localStorage.
In my opinion is not save to store the token in the local store,
As said in https://auth0.com/docs/security/store-tokens
Since Browser local storage (or session storage) is not secure. Any data stored there may be vulnerable to cross-site scripting. If an attacker steals a token, they can gain access to and make requests to your API. Treat tokens like credit card numbers or passwords: don’t store them in local storage.
A better option is to use cookies since they are managed by the browser.

Single sign on with OAuth2: saving refresh token in cookies

I need to implement centralised authentication server with single sign on.
One of the requirements are, that there should be no intermediate login screen (a.k.a direct login from service provider), so OAuth2 with password grant seems like the best option here.
User is read-only, authentication is used only to access specific content, which is the same for all users, the users can't change their personal data or anything else. We use user ID as an username and date of birthday as a password, it's not really secure, but that's not something we can control, because we get credentials from other 3rd party service, though we still want to make everything secure as possible, because user data includes such personal data as full name and home address.
To make it clear, next I will describe how I imagine OAuth2 and SSO flow to work together:
User enters his credentials and submits the login form in service provider
Service provider (SP) sends a request to identity provider (IdP), to check if credentials are valid (Request is signed with client id and secret as a base64 bearer token: base64(client_id:secret))
If credentials are valid, IdP creates access token (5min) and refresh token (24h) and returns them to SP
On every user request, SP uses access token to receive user data from IdP
If token is expired, SP makes another request with refresh token to retrieve new access token. Request must be signed with client id and secret.
So it's pretty much, how OAuth2 password grant would work, probably hardest part is to make it work with SSO, I couldn't really find any working stateless implementations, so came up with this:
When access and refresh tokens are issued, IdP stores refresh token in a cookie.
When user visits SP for the first time, quick redirect to IdP is made, if refresh token exists in a cookie it’s added as query param to the redirect url and user is redirected back to SP. If no, some query param is added to identify, that user is not logged in, to avoid redirect loop.
SP uses retrieved refresh token to issue new access token (which is unique for every SP).
So access token can be used only by service provider, which it was issued for. And refresh token, can be used by all service providers, but to issue new access token client id and secret must be provided, so refresh token alone is useless.
Also forgot to mention that all websites use TLS.
What do you think about this implementation, is it secure enough? Maybe you have other suggestions?

Rest API JWT token based authentication security | laravel/dingo/jwt

I am using JWT token based authentication for the authenticating my REST APIs exposed to mobile apps. I have a login API where the user will be hitting to and get a JWT back as a response. App has to use the JWT token for the rest of the requests. One question that struck during the development is.
Once I give an authentication token to the user, he has access to rest of the set of APIs.
User 1 with JWT token T1 trying to access resources of user 2 is possible in my current design which is a flaw in my system. On each request do I have to check whether the user id in the token and the user id for which the process is requested matches and then proceed? or is there any better way this is been handled some other way?
I am using laravel framework with dingo rest and JWT lib.
Update
Eg :
I as an individual got the endpoints from the app. I logged in and received my jwt token which will be valid across rest of my resources. Now to get a list of products I have added using a different user id.I can do it this way
My JWT token in the header
GET /products/3 and 3 is not my user id!
In this case, Im just validating a jwt token, which will validate it and respond with the resource which is not MINE!
TL;DR: It is imho quite common to use it this way, you should be good the way it is!
More detail:
The point here is that the token is "obscure enough" so that there is an negligable chance a non-authorized user is obtaining the token from an authorized user. In your example this means, that user 2 can with a very high probabilty not guess the token that user 1 is using.
Of course this way may be prune to man-in-the-middle-attacks, so you should be sure to only transfer the tokens over a secure connection. I suggest "HTTPS only". Also, you may think about only sending and receiving the tokens in the header, so they are not exposed in any content views.
As a bit more background: Think about how PHP "standard" session cookies are working: The user (client) gets a session ID in a cookie and sends it back. This is basically the same as you are doing here with the JWT, as user 2 could also somehow steal the cookie from user 1 here, and act on his behalf. JWT even adds you a level with which you can easily confirm that you actually issued the token (provided you are using the RSA-keypair-style approach), which i think is an advantage over the PHP session ID cookie approach.

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"
}

Secure login with Twitter oAuth - best practice

I am new to oAuth and looking to build a web application using Twitter (oAuth) to authenticate. There will be no other login method other than via Twitters oAuth. I am looking for advise on best practice to secure the site based on tokens. Here is my plan:
User is taken from my site to authenticate via Twitters site
Generate Access token for user
Get the users unique Twitter id via Twitter API
Do a user lookup in local db with this id and locate access token if available.
If no user, create new row in user table and save against the user. If user found, update access token agains the user record.
If the user is found, md5_salt the twitterid and set as a cookie.
If the user re-visits, lookup user based on cookie
Does that sound like a secure approach or is using the md5 twitter id a bad idea?
Appreciate any comments.
Without knowing exactly what your client/consumer application is doing, it is hard to tell whether this approach will be "secure".
One problem I see, is that once you have an access token from twitter, how do you identify your user if the cookie gets deleted? Or would you require them to get a new access token? This would mean that they would have to both login, and authorize your application each time.
Also, an access token for one user of your app. can be stolen and used by another user of your app. since it works just like a password AND you have no authentication on your side to verify your cookie saved access token.
To answer your question then, I would have to say that using oauth as the only authentication provider, no matter how you do it, is not a best practice.
In order to be secure both the client (consumer) application, and the server (provider) application, need to verify the identity of your users. The easiest way to do this is with a username and password which are stored in your users head, and not on file somewhere...

Categories