Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Receiving 401 Unauthorized after auth token expiration #102

Open
cnd5041 opened this issue Feb 2, 2017 · 18 comments
Open

Receiving 401 Unauthorized after auth token expiration #102

cnd5041 opened this issue Feb 2, 2017 · 18 comments
Labels

Comments

@cnd5041
Copy link

cnd5041 commented Feb 2, 2017

Hi, I am using the server code, and have login/authentication working with Shared UAA, it's hooked up to redis and everything and running in CF/Predix.

The issue I am seeing is that when I go to the site the next day, I am only receiving a 401. I'm assuming the auth token is expired, but it does not seem to be redirection.

I have the entire app secured via this code in app.js:

//Use this route to make the entire app secure.  This forces login for any path in the entire app.
    app.use('/',
        passport.authenticate('main', {
            noredirect: false //Don't redirect a user to the authentication page, just show an error
        }),
        express.static(relRootPath)
    );

I am wondering if there is something wrong with the passport configuration?

@gstroup
Copy link
Collaborator

gstroup commented Feb 2, 2017

Good question. I haven't seen this behavior myself. It's possibly a passport config problem, but the '/' root path should redirect back to the UAA login page. Is your app using calling some other route that could give you the 401?

@cnd5041
Copy link
Author

cnd5041 commented Feb 3, 2017

No, the only other routes are to an API, but those aren't protected right now, they're just attaching the auth headers.

I'm guessing it's passport/configuration. It's odd that in a fresh session, it re-directs, but does not in the case of an expired token.

@gstroup
Copy link
Collaborator

gstroup commented Feb 3, 2017

OK, I'll try to reproduce and fix, but it might take a few days. :) This line looks wrong to me:
https://github.com/PredixDev/predix-seed/blob/master/server/passport-config.js#L14
I'm thinking that authenticationURL should be set to predixConfig.uaaURL, same as the other strategy...

@cnd5041
Copy link
Author

cnd5041 commented Feb 4, 2017

Very possible. I'll have to give that a try.
Thanks for the help.

@papscript
Copy link

I have similar issue when i log in to the app, leave for the night (or just wait for token expiration) and access some secure route.
Then I'm redirected to the login page, and log in properly. I have access to secured routes of my webserver but I get 401 (invalid token) if I want to access secured backed services (spring boot).

When I remove session cookie manually or logout (which destroys session cookie as well) and then log in back everything's work fine.

Should I destroy session cookie on every 401? But it doesn't sound like a clean solution. I migrated to nodejs/express from nginx recently. I haven't this issue before.

PS When I set authenticationURL = predixConfig.uaaURL i couldn't even log in :)

@gstroup
Copy link
Collaborator

gstroup commented Mar 16, 2017

I think we do have some issues with refreshing tokens in the seed app. We'll investigate and try to fix in our next release. @cnd5041 Have you made any headway on this issue?? Thanks.

@gstroup gstroup added the bug label Mar 16, 2017
@cnd5041
Copy link
Author

cnd5041 commented Mar 16, 2017

@gstroup I haven't tried it with Redis yet.
I set the cookie.maxAge in the sessionOptions (to be shorter than your token validity).

cookie: { maxAge: 7000 },

@papscript
Copy link

I set the cookie.maxAge as you suggested and it seems to work, but I need to test it a little bit more.

@davidsteinberger
Copy link
Collaborator

We've been bitten by this issue too. Is there a good workaround?

@cnd5041
Copy link
Author

cnd5041 commented Mar 30, 2017

@davidsteinberger There is not a Redis workaround that I know of yet. See comments above about the cookie and maxAge. It's using the session rather than redis.

@gstroup
Copy link
Collaborator

gstroup commented Mar 30, 2017

Yeah, I think the workaround is to set the cookie max age, like @cnd5041 says. Normally, you want your web server session to expire before the oauth token expires. This should prevent the problem. I'm still testing it myself to verify, but I think it's a good fix. Planning to include it in the predix-seed soon. (This is not related to redis, just web server session expiration vs. oauth token expiration.)

app.use(session({
	secret: 'predixsample',
	name: 'cookie_name', // give a custom name for your cookie here
        maxAge: 30 * 60 * 1000,  // expire token after 30 min.
	proxy: true,
	resave: true,
	saveUninitialized: true}));

@papscript
Copy link

For me it's working fine since I've implemented it two weeks ago. But don't you all think it's a little bit dirty hack? And what about refresh token, will the change affect it?

@jendfrench
Copy link

jendfrench commented Jul 6, 2017

I know that this project has moved, but I wanted to let you know that in my case this issue (specifically, the issue that @PiotrekPaprocki mentioned where a secure springboot backend is returning 401) was due to proxy.js not getting a new client token after the client token has expired. I modified proxy.js to store client token expiration datetime in the session as well, then check for expiration before adding the client token to the request headers.

var addClientTokenMiddleware = function(req, res, next) {
	function errorHandler(errorString) {
		res.send(errorString);
	}
	if (req.session) {
		if (!req.session.clientToken) {
			getClientToken(function(token, expiresIn) {
				req.session.clientToken = token;
				var clientTokenExpires = moment().add(expiresIn, 'seconds');
				req.session.clientTokenExpires = clientTokenExpires.unix();
				req.headers['Authorization'] = req.session.clientToken;
				next();
			}, errorHandler);
		}
		// check if token is expired.  Subtract 10s from expire time because if it's that close to expiring we should just get a new one.
		else if (moment.unix(req.session.clientTokenExpires - 10).isAfter(moment())) {
			req.headers['Authorization'] = req.session.clientToken;
			next();
		}
		else{
			getClientToken(function(token, expiresIn) {
				req.session.clientToken = token;
				var clientTokenExpires = moment().add(expiresIn, 'seconds');
				req.session.clientTokenExpires = clientTokenExpires.unix();
				req.headers['Authorization'] = req.session.clientToken;
				next();
			}, errorHandler);
		}
	} else {
		next(res.sendStatus(403).send('Forbidden'));
	}
};

I made a few other modifications in the proxy.js file in order to get this to work. Hope this helps!

@jendfrench
Copy link

jendfrench commented Jul 6, 2017

Also, @gstroup - regarding cookie expiration and oauth token expiration, after I resolved the client token issue above, I set my cookie maxAge to be the length of time my refresh token is good for (in my case 8 hours). The passport strategy used in this app will not get you another oauth token after the refresh token expires unless you start a new session.

@gstroup
Copy link
Collaborator

gstroup commented Jul 6, 2017

@jendfrench Thanks for the detailed info! Yes, your solution makes sense. At some point, I'm planning to switch over to use this little package, which handles the expiration, much like you did:

https://github.com/predixdev/predix-uaa-client

@gaikwadrahul20
Copy link

Hi @jendfrench I am also facing the same issue, I have replaced your code which gets the new token after it expires but somehow it is not solving the problem of 401 for secured api calls. I have to refresh the page to make it work.

@prijilnath
Copy link

prijilnath commented May 8, 2018

@gstroup There is any update for the same

@gstroup
Copy link
Collaborator

gstroup commented May 8, 2018

This project is no longer being maintained. But we have fixed this issue in the new predix-webapp-starter, by using the predix-uaa-client

https://github.com/PredixDev/predix-webapp-starter/blob/master/server/routes/proxy.js#L135

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants