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.
Related
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/
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.
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
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.
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.