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/
Related
I'm authenticating client side throught Firebase SDK the users to my app.
A clientside session is then started. I want the user then to be able to post to PHP endpoints some data. I want the PHP script to check if the request is coming from a authenticated user and then validate the rest of the data. If everything is ok, we finalize the operation.
I thought to do it like this:
User is authenticated client side
On Auth event a request for a JWT token with the user id in it is issued client side via ajax to a dedicated PHP script. Once the token is generated it is stored in a session cookie.
The form submit will carry the JWT token and the endpoint will decode the token and check if the uid stored in it is a valid user id registered in the Firebase DB.
Good or terrible idea from a security point of view?
First rule of thumb is that in order to validate a Firebase-generated JWT, you need the secret to your Firebase. Second rule of thumb is that your Firebase secret should never be sent or stored on a client.
Given that, to validate a JWT via PHP, you will need to use a library which decodes it and verifies it has been signed by your Firebase secret. Once you've verified that, I would look at the JWT's uid and see if it matches the uid of the user who owns the resource.
I'm using Oauth2 php library. I've followed the docs here and here
This is what I have so far:
a client application requests a token using client id & client secret
to the client_credential end point
a token is returned to the client app with a basic scope
a user logs in from the client app
the client application requests a new token using user id & user
password to the user_credential end point
the client app receive a new token with the new scope of the user
Everything works.
The only thing that doesn't make sense to me is that I have to pass again the client id & client secret when doing the user authorization (grant_type:'password') otherwise wise it doesn't work.
{"error":"invalid_client","error_description":"Client credentials were not found in the headers or body"}
My understanding was that since I obtained first a client token, I wouldn't have to identify the client again. I've tried passing the token instead of client id & client password for user auth but no go. What's the proper grant type combination for what I'm trying to do ?
A (single) client is either public, i.e. it has no client_secret associated with it, or confidential i.e. it uses a client_secret to identify itself. It cannot be both at the same time. What you could do is register a second client with a different client_id as a public client, so it won't have to use a client_secret to identify itself to the Authorization Server. You could then use that second client_id from your (single) client app in the second part of the desired flow.
I'm building a mobile app for my website using Phonegap and I am using PHP Codeigniter framework to create my REST API. I need to allow users to log in to the app and retrieve information but I am little confused on the authentication part.
Right now this is what I have in mind:
User logs in with username/password (they will be send to the server using HTTPS)
My API will check the db to see if the user exists
If the user exists generate a random string (token) and send it back to client
On the client side (mobile app), store the token somewhere
Every time user requests information from the server, send the token for validation
I decided to go with token method because I needed to allow users to stay logged in to the app once they login for the first time (I read that storing username/password on client side is bad).
So here are my questions,
Is my method valid/safe? If so how is token stored on phonegap? Will localStorage do the job?
Is there a better & simpler method?
Are there libraries that could help me do this easier/faster? especially with building REST API?
Lastly, I heard about OAuth2 but is this only for when you want to allow 3rd party logins (google, facebook etc)? I've looked into it and there seems to be an OAuth for PHP and OAuth for Phonegap. If I implement this, will I need to do it in my REST API AND phonegap side?
I'm fairly new to all this so any explanations with examples will be helpful.
I suggest to use your token method.Every time app launches check the localstorage for user token is set if not set up http request and store the token in localstorage.
Here is sample code
function validateUser(username,password){
//get the user token from local storage
if(window.localStorage.getItem('usertoken')==null){
//set up the http request
$.ajax({
url:'www.example.com/login.php',
method:post,
data:{'username':username,'password':password}
success:function(data){
//set the token in localstorage
window.localStorage.setItem('usertoken',data);
}
});
}
}
}
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
I would like to use Google Plus Sign-In to authenticate my users in an iOS app. I have followed the guide for iOS described on https://developers.google.com/+/features/sign-in. The sign in on client side works perfectly with the Google + Platform. I have not understood how to authenticate the user on server side.
I have seen that the access token on the client can be validated to some extent on https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=XYZ123. Is it safe to authentice a client by validating the access token that the user sent over HTTPS?
Are there better solutions when using the Google+ Sign-In button on the client? As I understand it, Google recommends using the Google+ Sign-In button:
The Google+ Sign-In button is an easy way for users to sign up and sign in to your app. This allows you to know who they are on Google+ and to build a more personalized experience for your app, all without having to create yet another username and password
Short answer: yes. On iOS that's the best method of going about it right now. The important thing is that your verification checks what you want, generally:
The client ID is a client ID from your project.
You only use the user ID from the access token
The token isn't expired
The expiry, and other basic verification, is handled automatically when you called tokeninfo. Just make sure you check the client ID, and use the user ID from the the tokeninfo response to look up the local user.
{
"issued_to": "1234.apps.googleusercontent.com",
"audience": "1234.apps.googleusercontent.com",
"user_id": "104824858261236811362",
"scope": "https://www.googleapis.com/auth/plus.login",
"expires_in": 3584,
"access_type": "online"
}
This is an example of the response. The client ID is the "audience" field here (actually, also issued to), and the user_id is the Google user ID - that's what you should look up in your database to find the matching application user.
On Android and the web there are two other options: retrieve an ID token (basically a cryptographically signed token that directly contains similar information to what you get back from calling tokeninfo with the access token), and retrieving a code (that can be used to exchange for an access token and id token on the server side). Those two aren't currently available on iOS, so passing the access token via HTTPS is the best option currently.