Google Auth token from Chrome Extension with PassportJS returns 401 Unauthorized - express

I'm trying to set up a Chrome Extension that uses chrome.identity.getAuthToken to get the logged in user's auth token and then use that to authenticate with an Express server using Passport and the passport-google-token strategy.
getAuthToken is giving me the token but when it's sent to my server, I'm getting a 401 unauthorized error.
I'm pretty new to Passport and to token based authorisation in general, so I'm not sure if I've made a mistake or misunderstood how it's meant to work.
My chrome extension does this:
chrome.identity.getAuthToken({"interactive": true}, function(token){
var url = "http://localhost:30000/auth/chrome";
var x = new XMLHttpRequest();
x.open("GET", url);
x.setRequestHeader('Authorization', "Bearer " + token);
x.send();
});
and the token is being correctly passed into my callback.
I set up my Express server and Passport strategy like this:
import * as express from "express";
import * as passport from "passport";
const GoogleTokenStrategy = require("passport-google-token").Strategy;
// set up Express and Passport...
passport.use(new GoogleTokenStrategy({
clientID: --client id--,
clientSecret: --client secret--
}, (accessToken, refreshToken, profile, done) => {
return done(null, profile);
}));
app.get('/auth/chrome', passport.authenticate("google-token"), (req, res) => {
res.send(req.user);
});
The client ID and secret come from the credentials I've set up at the Google API Manager:
If anyone can point me to what else I need to do or what I'm doing wrong, it would be much appreciated.

There were two reasons this was failing for me.
The first, which I realised when I stepped through some of the passport-google-token code, is that it fails if req.body is undefined. I fixed that by adding the body-parser middleware.
The main problem though was the way I was sending the access token in the header. I had copied x.setRequestHeader('Authorization', 'Bearer ' + token); from one of the Google sample apps but it actually needed to be sent as:
x.setRequestHeader('Access_token', token);
or in the query string as:
var url = "http://localhost:30000/auth/chrome?access_token=" + token;

Related

React Native - Axios - Google Identity Refresh Token 401 error

I'm using custom tokens and firebase auth. I'm successfully logging in users with email & password and storing the accessToken and refresh tokens. When I go to use the refresh token to get a new access token I'm getting a 401 error. When I try the same post link I'm using in a chrome extension based plugin (for testing REST API's) - the request is successful and I get the desired response. Though with my code in expo & react native I get just a plain, unhelpful 401 error.
My code is as follows:
const headers = {
'Authorization': `Bearer ${accessToken}`
}
const data ={
grant_type : "refresh_token",
refresh_token : refreshToken
}
await axios.post(urlTest, data, {
headers: headers
})
.then((response) => {
console.log("Success! ", response)
})
.catch((error : Error) => {
console.error(error.name, error.message);
})
Not sure what I'm doing wrong here. Maybe a cors issue? A fresh pair of eyes would be welcome.
Thanks!
Seems it might have been a CORS issue. Changed where I was hosting the code to handle posting and getting new access token. Works a treat now.

Run custom functions in express-gateway

I have this configuration in the gateway.config.yml (Express-Gateway api):
- bo
policies:
- jwt:
- action:
secretOrPublicKeyFile: './key.pem'
checkCredentialExistence: false
Everything works fine, but I want the client to encode/encrypt a token that it is being sent to make sure even if I have the token storage on the localstorage no one can use it because it will need to be signed by the client.
The only problem with this is, how can I run a code to decode/decrypt the token before Express-Gateway jwt policy try to validate the token?
Because express-gateway can use middlewares like any other express application I think this is possible, but not an idea on how to do it.
I created this policy that will help me, but how can I integrate it with the express-gateway api:
const cryptojs = require("crypto-js");
module.exports = {
name: 'decode',
policy: (actionParams) => {
return (req, res, next) => {
const tokenHeader = req.header('Authorization');
const tokenArray = tokenHeader.split(' ');
const tokenCifer = tokenArray[1];
const bytes = cryptojs.AES.decrypt(tokenCifer, 'superkeyperm'); //CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123');
var token = bytes.toString(cryptojs.enc.Utf8);
req.headers.authorization = `Bearer ${token}`;
next() // calling next policy
};
}
};
I think what you're interested is writing a plugin which is nothing more than a collection of additional middleware and condition you can stack in Express Gateway, where you can put your own logic.
Check out the docs at https://www.express-gateway.io/docs/plugins/

How to store jwt token in localStorage and send it back to the server with header in express?

I have read many articles in stackoverflow and have seen lots of youtube videos, but failed to find the example code which is demonstrating about the flow of saving jwt to localstorage - send back to server with authorization header for verifying.
Here is what I want to do.
When the client logs in to the server, server gives token and saves it to the client localStorage (or sessionStorage).
Whenever the client calls an api which can be accessed only with the token,
client retrieves the token back from the localStorage, and send that token with the authorization header (req.headers.[x-access-token] or req.headers.[authorization]) to the server.
But all of the articles I've been read is explaining this issue with the Postman which does not show how to store it to the localStorage and put it in the authorization header.
Do I have to use localStorage.setItem when the server gives the token to the client, and use and localStorage.getItem and new Headers() with append() or axios before sending that token back to the server?
Examples don't have to be for the express user, but I'd like to get the glimpse of ideas.
You can store your jwt token in localstorage and when ever you make a API call you can add the token to headers as token. if you are using axios you can attach you token to headers like this. Here the token is stored in localstorage with the key 'jwtToken'
axios.post('http://yourendpoint',data,{ headers: { Authorization:localStorage.getItem('jwtToken') } })
.then(response=> console.log(response))
.catch(error => console.log(error));
};
it's easy just Follow me
First of all you have to save the Token(or access token) to the local storage,
in the login component when you are sending request for login do the below:
signin:function() {
axios.post('http://Somthing/log-in/',{
username: this.username,
password: this.password,
})
.then( (response) => {
let token = response.data.access;
localStorage.setItem("SavedToken", 'Bearer ' + token);
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
(this.$router.push({name:'HomePage'}));
})
So now the problem is whenever you refresh the Homepage you got 401 error and the solution is : just add this :
{ headers: { Authorization:localStorage.getItem('SavedToken') }}
to the end of each request that need the Token in its header, like below:
axios.get('http://Something/', { headers: { Authorization:localStorage.getItem('SavedToken') }})
.then(response =>{
//something
})
Notice that the token that i used in this explanation was SIMPLEJWT , if you are using somthing else maybe you have to change 'Bearer' to somthing else.
First you have to create or Generate Token through Jwt (jsonWebTokens) then either store it in local Storage or through Cookie or through Session. I generally prefer local storage because it is easier to store token in local storage through SET and retrieve it using GET method. and after retrieving it through get you can verify it through jwt and also authenticate it with bearer authentication..
And for headers add Authorization
fetch("/users", {
method: "Get",
headers: {
"content-type": "application/json",
Authorization: "Bearer" + localStorage.getItem("token")
}
JWTs should never be stored in your localStorage
In fact, they shouldn't even be stored in your cookies, unless you are able to implement very strict CSRF protection
Checkout this for motivation
JWT as an id_token is like your user credentials
JWT as an access_token is like your session token
One option is in-memory. Checkout this for a deep dive

Perform a log-out using stormpath $http

I am trying to revoke oauth2 tokens using the stormpath API. Server-side authentication is performed using stormpath + express. Here is my request.
function revokeOauthTokens(params) {
// Revoke the oauth2 access. and refresh tokens
var oauthLogoutReq = {
method: 'POST',
url: params.apiBaseUrl + '/logout',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: 'grant_type=refresh_token&refresh_token='
+ params.oauth_tokens.refresh_token
}
return $http(oauthLogoutReq);
}
Where apiBaseUrl is my nodejs base url and ouath_tokens contains the response granted by a request to /oauth/token endpoint.
Looking at the documentation at the following links leaves me confused.
http://docs.stormpath.com/nodejs/express/latest/logout.html
http://docs.stormpath.com/guides/token-management/
Thanks.
This is a great question. As you’ve seen, express-stormpath is using secure, http-only cookies for token storage, and this doesn’t work for Cordova, Electron, etc, where cookie storage isn't implemented to spec. The alternative is local storage, or some other storage API that is provided to you (hopefully a secure one!).
The express-stormpath library does provide a /logout route, and it does revoke tokens, but it’s looking for the tokens in cookies. We need to add a new route, likely /oauth/revoke, to support explicit token revocation.
This is pretty easy to add right now as a custom route handler, and I’m including a link below. But please be aware that express-stormpath uses local token validation by default. This is done for speed (no roundtrip to our API) but the caveat is that your local server will NOT know that the tokens have been revoked, and can technically still be used for authentication if a malicious third party has stolen them from your client. If this is a concern you want to to address, you should opt-in to stormpath validation, which will always require a check against our token database. This is documented here:
http://docs.stormpath.com/nodejs/express/latest/authentication.html#token-validation-strategy
All that said, here is the route handler that you could wire up as /oauth/revoke, and have your Electron client use it to revoke the tokens when the user logs out:
'use strict';
var revokeToken = require('express-stormpath/lib/helpers/revoke-token');
function defaultResponder(res, err) {
if (err) {
console.error(err); // or your system logger
return res.status(err.status || 400).json({
message: err.developerMessage || err.message
});
}
res.end();
}
/**
* Implements the expected behavior of the /oauth/revoke endpoint, and requires
* that token_type be defined. This assumes that you are using the express-stormpath
* module, so that your Stormpath client and configuration context is available.
*
* #param {Object<ExpressRequest>} req Express JS Request
* #param {Object<ExpressResponse>} res Express JS Response
*/
function revokeTokens(req, res){
var client = req.app.get('stormpathClient');
var config = req.app.get('stormpathConfig');
var secret = config.client.apiKey.secret;
var token = req.body.token;
var token_type = req.body.token_type;
if (!token || ! token_type) {
defaultResponder(res, {
message: 'token and token_type fields are required'
});
}
if (token_type === 'access_token') {
revokeToken.revokeAccessToken(client, token, secret, defaultResponder.bind(null, res));
} else if (token_type === 'refresh_token') {
revokeToken.revokeRefreshToken(client, token, secret, defaultResponder.bind(null, res));
} else {
defaultResponder(res, {
message: 'invalid token_type'
});
}
}
module.exports = revokeTokens;
If you find that you don't want to use express-stormpath and would like to use something more direct, you can drop down to the Stormpath Node SDK and use it for token revocation:
https://docs.stormpath.com/nodejs/jsdoc/AccessToken.html
Or you can make DELETE requests directly against our API:
https://docs.stormpath.com/rest/product-guide/latest/auth_n.html#revoking-access-and-refresh-tokens
In both cases, you would be doing that from your server, not the Electron application.
I hope this helps!
-Robert

Auth between a website and self-owned API

This has probably been asked before, so a preemptive apology from me.
I built a site and I built an API. The API will also be used by a mobile app in the future. I own both so I'm pretty sure two and three legged OAuth aren't for me. The API has parts that are accessible to the world and other parts that are protected and require a user account. To keep things simple I've just gone with a https + Basic Auth solution (for now). It's all fine and good when testing requests manually to the API (I didn't write tests because I'm a bad person), things work as expected and Basic Auth is fine.
I'm trying to solve the flow of a user logging in with plaintext user and password, send that to the API to authenticate, the API just needs to say yes or no, yet all requests from the site (on behalf of a user) to the API should be signed in some way with their credentials for when they want to POST/GET/PUT/DEL one of the protected resources.
Out of all of the auth resources I've read I'm still confused as to what scheme to use. Storing the plaintext password on the site side so that I can base 64 encode it and send it over the wire seems bad, but it looks like that's what I'd have to do. I've read of digest auth but I'm not sure I get it. Any and all advice is welcome.
This is how I would handle this case;
POST the username and password as a plain text to your api using HTTPS of course.
Then validate it to your database, the best algorithm used nowadays to salt password is bcrypt.
If the user is not valid return 401, or whatever.
If the user is valid, return a JWT token with his profile signed with a Public Key algorithm.
Your fron-end knows the public key so it can decode the JWT but it can't generate a new one.
For every request that needs authentication, you attach an Authentication header, with Bearer [JWT]
A middleware in the backend reads this header and validate it with the private key.
Don't be affraid of JWT there are plenty of implementations for every language and framework and is easier than you might think. A lot of applications are already using JWT already even Google.
Auth0 is an authentication broker that can validate against any identity provider or custom database, and returns JWTs. It provides a clientID that can be used to decode the profile in the front end and a secret to validate the tokens in the backend as well as client side library to do this.
Disclaimer: I work for auth0.
Update: Since you mention node.js and express in comments I will give an example in this technology.
var http = require('http');
var express = require('express');
var jwt = require('jsonwebtoken'); //https://npmjs.org/package/node-jsonwebtoken
var expressJwt = require('express-jwt'); //https://npmjs.org/package/express-jwt
var secret = "this is the secret secret secret 12356";
var app = express();
app.configure(function () {
this.use(express.urlencoded());
this.use(express.json());
this.use('/api', expressJwt({secret: secret}));
});
//authentication endpoint
app.post('/authenticate', function (req, res) {
//validate req.body.username and req.body.password
//if is invalid, return 401
var profile = {
first_name: 'John',
last_name: 'Foo',
email: 'foo#bar.com',
id: 123
};
var token = jwt.sign(profile, secret, {
expiresInMinutes: 60*5
});
res.json({
token: token
});
});
//protected api
app.get('/api/something', function (req, res) {
console.log('user ' + req.user.email + ' is calling /something');
res.json({
name: 'foo'
});
});
//sample page
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
http.createServer(app).listen(8080, function () {
console.log('listening on http://localhost:8080');
});
This is an express application with one endpoint that validates username and password. If the credentials are valid it returns a JWT token with the full profile, with expiration 5 hours.
Then we have an example endpoint in /api/something but since I've a express-jwt middleware for everything on /api it requires a Authorization: Bearer header with a valid token. The middleware not only validates the token but also parses the profile and put it on req.user.
How to use this client-side? This is an example with jquery:
//this is used to parse the profile
function url_base64_decode(str) {
var output = str.replace("-", "+").replace("_", "/");
switch (output.length % 4) {
case 0:
break;
case 2:
output += "==";
break;
case 3:
output += "=";
break;
default:
throw "Illegal base64url string!";
}
return window.atob(output); //polifyll https://github.com/davidchambers/Base64.js
}
var token;
//authenticate at some point in your page
$(function () {
$.ajax({
url: '/authenticate',
type: 'POST',
data: {
username: 'john',
password: 'foo'
}
}).done(function (authResult) {
token = authResult.token;
var encoded = token.split('.')[1];
var profile = JSON.parse(url_base64_decode(encoded));
alert('Hello ' + profile.first_name + ' ' + profile.last_name);
});
});
//send the authorization header with token on every call to the api
$.ajaxSetup({
beforeSend: function(xhr) {
if (!token) return;
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
}
});
//api call
setTimeout(function () {
$.ajax({
url: '/api/something',
}).done(function (res) {
console.log(rest);
});
}, 5000);
First, I've an authenticate call with the username and password, I can decode the profile in the JWT to get the user profile and I also save the token to use in every request later on.
The ajaxSetup/beforeSend trick adds the header for every call. So, then I can make a request to /api/something.
As you can imagine this approach doesn't use cookies and sessions so it works out of the box in CORS scenarios.
I'm a big fan of passport.js and I've contributed a lot of adapters and fixes for some other adapter but for this particular case I wouldn't use it.
I've been thinking about a similar scenario lately; here's what I did:
SSL + Basic Auth
In the DB (on the API side), generate a random salt (per user), and save the salt and the hashed (password + salt). When a request arrives, throw on the salt and hash it, then compare to what you've saved
Send the password in plaintext - you are using SSL so I think this is okay (this is the part I am most uncertain of)
I don't have a great reason for recommending this but in case you have a reason to use it:
.4. Attach a timestamp to every request and have them expire after a couple of minutes.
The reason you should save salted-and-hashed passwords in your DB is in case someone steals your DB.
Basically I'm putting a lot of faith into SSL, and what I've read tells me that's okay.