Implementing API key communication - php

I'm designing a client-server communication just for learning purposes for now.
On the server's side is php restful server and on the client's backbone js app.
The basic idea:
after successful login, server will generate unique API key, store it into DB and it will expire after some time of account inactivity
client will obtain this key and user id, save it in secure cookie and use it with every request
if keys are a match, server will process the request
all communication is on https
Is this process safe or what would you suggest?
And I really dont want to go with Oauth.

While ago, I've create a reference for API token based authorization, located here.
Something I do in one of the projects.
User signups, and API key is being generated.
User saves the API key to localstore or secured cookie.
To access API he has to exchange API key to Access Token. He sends request to endpoint and is userId and apiKey matches, HMAC-bases access token is issued.
All API requests require access token passed either by access_token query parameter or token value in cookie.
All that have to work on SSL.

Related

Ionic Token authentication php Server - Security questions [duplicate]

I have two applications:
server ( REST API Server)
node js
Express
jsonwebtokens
express-jwt
mongoose
client (Portable Front-end)
bootstrap
Angular JS
local-storage
angular-facebook
angular-jwt
Lateron, the client app will be ported for android, iphone and other platforms using phonegap. For OAuth, I am using Facebook as the provider. Now, I just realized JSON Web Tokens are the way to go for this kind of set up. My question is an architectural one rather than syntactical one - how to manage a secret key when signing the facebook access token and user id with JWT in nodejs?
So this is how the flow works in my app:
Angular client has a Login button
User Clicks the button > Facebook Auth starts
Client receives user_id and FB Access Token
Client sends[POST json body] both user_id and Access Token to Node+Express Server at 'http://server.com/auth/login'
Node Server has applied express-jwt to all routes except /auth/login with a
var expressJwt = require('express-jwt');
var jwt = require('jsonwebtoken');
app.use(expressjwt({ secret: ''}).unless({path: ['/auth/login']}));
Node server receives data from req.body, fetches all profile details from facebook using the JavascriptSDK, and signs it using
var token=expressjwt.sign({profile}, );
Node Server stores(updates, if user_id exists) the new token in db and sends it as response to client
client stores the new token it received as json data in local-storage
client uses angular-jwt to fetch profile data from the new token and automatically attach the new token in Authorization header for all requests it sends to the server
Now, my questions are:
Do I really need to store the JWT tokens in database? I am certainly not comparing the tokens in request headers with database
Do I need to generate random secret keys for security, each time a person logs in? If yes then how would that fit in both client and server?
When and where do I need to check for token expiration? and How do I refresh it?
I am kind of lost about the design flow and mechanism.
Ad 1. You do not have to store the JWT in the database. User ID can be part of the payload, therefore there's no need for it.
Ad 2. It's a common practice for the server side app to use one secret key for generating all JWT.
Ad 3. Check if token has expired on each request to your API and disallow access if the token has expired, return 401 status code. Client app should prompt user for credentials and request new JWT. If you want to avoid users re-submitting the credentials you can issue a refresh token that later can be used to generate new JWT.
JWT refresh token flow
http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/

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

PHP Console Application with OAuth 2.0 Refresh Tokens, how to store?

I am working on a PHP project that utilizes the API from a few services. For a single API, it uses OAuth 2.0 authorization to authenticate the application's API access. However, I am unsure how I should approach the process to authenticate a local console application.
I would not be using a webflow to authenticate the API, as my PHP script runs in a local console. The API allows for the retrieving of the access token and refresh token by entering my username and password (they recommend this only for console applications).
Once I get the access token, I may use it to make API requests. This works fine. However, I am unsure what to do with my refresh token. The API consumes refresh tokens as such:
/oauth2/access_token/ (Refresh token usage)
Context: Client's Web Server
Required arguments: refresh_token, grant_type=refresh_token,
client_id, client_secret
Access token scope: None
On success, a JSON response is returned to the client:
{
"access_token": a valid access token,
"scope": scope as given in authorize,
"expires_in": seconds to expiry,
"refresh_token": a token that can be used to get a new access token
}
Consuming a refresh token will immediately expire the related access
token. Refresh tokens are single-use. A new refresh token is returned
from this call, ready for consumption later.
From what I gather from this, my authentication process should be something like this:
Initial authentication - pass username/password via environment variable, get the access/refresh token from response
Store the refresh token? Check for the expiry of the initial access token
If initial access token has expired, pull refresh token from file and make a request for a new access/refresh token
Store new refresh token?
Does this sound like the correct authentication flow? Is there a specific way I should be storing the refresh token? I am aware there may be a lot of security concerns for simply storing the refresh token in a text file, as it has the ability to give complete access to my account. Are there any better alternatives?
Thanks!
Authentication flow is fine. For more detailing and validation, you can read https://www.rfc-editor.org/rfc/rfc6749 .
You can store ‘Refresh token’ either in file or db using encryption key and this MUST only be transmitted using TLS. ‘Refresh token’ is used in senerios where server do want to some scheduled background activities like accessing of profile and related data from other oAuth server based on previous stored access token without asking user name and password again over and again. If in case ‘Access token’ is invalidated then ‘Refresh token’ will be used to get new ‘Access token’ to serve purpose.

Restful web service API user authentication on every single call

I need to create a REST api to authenticate a user the first time and retrieve other information based on this user for subsequent calls. If I'm not mistaken Restful services are stateless and therefore there is no need to store user information server side. My question is how can I guarantee user authentication for all the subsequent calls without a session?
This service is needed to create an android app that can display information on mobile.
You could use OAuth which is a widely used standard.
Another option is to use BASIC authentication over SSL. Any decent HTTP library would support BASIC auth. The client will be challenged the first time the request is made. Subsequent request need to send the BASIC auth headers over a secure line.
The there is the approach where you pass a secret to your client and use HMAC-SHA256 to send a hash of the URL params over to the server. Amazon does that and there is an article that covers how this is done. It is not as complicated as OAuth.
There are many approaches available but IMO your best best is to generate a AuthToken server side and return that to the client upon successful login. Then the client includes this on every request down to the server.
What I typical do is create a MD5 hash of a secret key and the the user's id- user's username - user's password - and the current date time. Then I store the token and the current date time in the db. on look ups after that I decode the token and compare the data points against the db values and if they match the user is good. This way is stateless and easily scalable.

REST API Authorization & Authentication (web + mobile)

I've read about oAuth, Amazon REST API, HTTP Basic/Digest and so on but can't get it all into "single piece". This is probably the closest situation - Creating an API for mobile applications - Authentication and Authorization
I would like to built API-centric website - service. So (in the beginning) I would have an API in center and website (PHP + MySQL) would connect via cURL, Android and iPhone via their network interfaces. So 3 main clients - 3 API keys. And any other developer could also develop via API interface and they would get their own API key. API actions would be accepted/rejected based on userLevel status, if I'm an admin I can delete anything etc., all other can manipulate only their local (account) data.
First, authorization - should I use oAuth + xAuth or my some-kind-of-my-own implemenation (see http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/RESTAuthentication.html?r=9197)? As I understand, on Amazon service user is == API user (have API key). On my service I need to separate standard users/account (the one who registered on the website) and Developer Accounts (who should have their API key).
So I would firstly need to authorize the API key and then Authenticate the user itself. If I use Amazon's scheme to check developer's API keys (authorize their app), which sheme should I use for user authentication?
I read about getting a token via api.example.org/auth after (via HTTPS, HTTP Basic) posting my username and password and then forward it on every following request. How manage tokens if I'm logged in simultaneously on Android and a website? What about man-in-the-middle-attack if I'm using SSL only on first request (when username and password are transmitted) and just HTTP on every other? Isn't that a problem in this example Password protecting a REST service?
As allways, the best way to protect a key is not to transmit it.
That said, we typically use a scheme, where every "API key" has two parts: A non-secret ID (e.g. 1234) and a secret key (e.g. byte[64]).
If you give out an API key, store it (salted and hashed) in you
service's database.
If you give out user accounts (protected by password), store the
passwords (salted and hashed) in your service's database
Now when a consumer first accesses your API, to connect, have him
Send a "username" parameter ("john.doe" not secret)
Send a "APIkeyID" parameter ("1234", not secret)
and give him back
the salts from your database (In case one of the parameters is wrong,
just give back some repeatable salt - eg.
sha1(username+"notverysecret").
The timestamp of the server
The consumer should store the salt for session duration to keep things fast and smooth, and he should calculate and keep the time offset between client and server.
The consumer should now calculate the salted hashes of API key and password. This way the consumer has the exact same hashes for password and API key, as what is stored in your database, but without anything seceret ever going over the wire.
Now when a consumer subseqently accesses your API, to do real work, have him
Send a "username" parameter ("john.doe" not secret)
Send a "APIkeyID" parameter ("1234", not secret)
Send a "RequestSalt" parameter (byte[64], random, not secret)
Send a "RequestTimestamp" parameter (calculated from client time and known offset)
Send a "RequestToken" parameter (hash(passwordhash+request_salt+request_timestamp+apikeyhash))
The server should not accept timestamps more than say 2 seconds in the past, to make this safe against a replay attack.
The server can now calculate the same hash(passwordhash+request_salt+request_timestamp+apikeyhash) as the client, and be sure, that
the client knows the API key,
the client knows the correct password

Categories