I started working on nodeJS token authentication and I encountered a weird issue. Is there any way I can make a link to the restricted page such that user sends Auth token to the server but without encoding it as a GET parameter in the request?
The only way I could solve it is to put the token into the session, but this solution kinda defeats the whole purpose of the token auth.
Any ideas?
Regardless of the technology (i.e. node), you want to send it as a header. In CURL, this is as simple as:
curl --header "token: ASDFASDFASJKDFLKL" http://www.example.com/protected
Depending on what you're using in node, you'll likely have a request (or req depending on how it's defined) parameter. Your header would be stored in request.headers
Related
I am resolving user data using firebase for auth like so:
from firebase_admin import auth
decoded_token = auth.verify_id_token(client_id_token)
I am initializing my firebase creds with firebase_admin.initialize_app(cred)
Here cliend_id_token is a token that the client sends. However, this takes around 1 second to perform, which seems way too long. One possibility is to use a caching layer above this (lru cache, memcache) but it still seems that it should not fundamentally take so long. Looking at the the signature of verify_id_token there does not seem to be anything that stands out as something that I can pass in:
def verify_id_token(id_token, app=None):
Any thoughts on how to diagnose (or if I am missing something)?
The problem is because that function does an http request in order to have the key to decode the jwt. In addition, because it returns info such as the email of the user, while the jwt contains only the uid as sub field of the decoded jwt, I think that it does another http request under the hood to get the user from the decoded uid.
You should implement your custom decode function, following the docs: https://firebase.google.com/docs/auth/admin/verify-id-tokens
I'm having the same issue. It's about 200ms for me (I'm using fastapi). #EuberDeveloper - glad to hear it's the same on node js - you saved me from testing it out.
I wanted to mention how I got my setup working faster in case anyone would benefit.
I've got Google API gateway with Firebase security defined in the swagger spec in front of a Cloud Run instance. API gateway validates the jwt (as per the swagger spec) and passes on the authorization header to the backend as a renamed header (from memory it's X-FORWARDED-AUTHORIZATION but best to double check). This is pretty fast.
Then in the backend you don't need to validate the id token since it'll already be validated by the time the request gets there. And if you send the UID along in the request to your backend as well as the idtoken in the authorization header, you can fetch users with the UID field you send. This removed that 200ms it was costing me to decode the id token.
Note - if you want to do things like check how old a refresh token is and revoke it for some reason then you'll still need to decode the id token.
I am using form authentication and role based access.
I want to make all the subsequent request as an authentication request using the access token.
I refer Loopback-example-access-control example, but not get a clear idea.
In this example, they pass access token using query string. My question is I want to make all the request as authenticated using access-token without pass query string or header.
Any other alternative way is available?
I need demo application that includes authentication and authorization, except loopback-example-access-control example.
Please help me, I am new to strong loop.
There are only three ways to send data to a server: path/query string, headers, and the request body. Since you don't want to use the query string (which is good, you really shouldn't) and you don't want to use a header (which is the most common and currently the industry standard) then you are left with only the request body. That's not a great choice either, and not supported by default in LoopBack, you would have to code that up yourself.
The right solution here is to use the Authorization header and send the access token in there with each request.
And just to be clear, this really has nothing to do with LoopBack, this is just token-based authentication basics. You must pass the token with each request, that's how the system works, there is no alternative.
I am a web application newbie. I know that XSRF protection questions have been asked in SO but the questions have been specific to a particular language (RoR/Python for example) or a library (jQuery). I would like to know how I can implement XSRF protection in my web application.
My understanding is that XSRF protection relies to using a unique random token that must be authenticated when a HTTP request is made. I have the following questions:
When should the authentication token be initialized? Should it be set on page load (i.e. GET request)?
Where should the token be initialized? Should they be set in input fields, cookies or request headers? How is this random value generated? How do I persist this value in order to be used for comparison?
When should the authentication token be verified? How does I compare authentication tokens? How do I compare these tokens with the token that I have persisted?
Is there a difference in the set up for a synchronous form request versus an AJAX request?
When should the authentication token be initialized?
The first time, during a session, that the user arrives at a page containing any form that you wish to protect from CSRF attacks.
Should it be set on page load (i.e. GET request)?
It should be embedded in the form when the HTML for it is generated.
Should they be set in input fields, cookies or request headers?
Hidden inputs.
Using a cookie would miss the point (which is that it comes from the page and does not persist in the browser). Extra headers can only work when using XHR, use a general approach.
How is this random value generated?
With a random number generator
How do I persist this value in order to be used for comparison?
Sessions
When should the authentication token be verified?
As part of the authorization step.
How does I compare authentication tokens? How do I compare these tokens with the token that I have persisted?
if ( $request->paramaters->{csrf} eq $session->data->{csrf} )
Is there a difference in the set up for a synchronous form request versus an AJAX request?
No. You still have a session and you still have a piece of the POST data being the token.
I'm not going to talk about a specific solution that you must follow as there are many, I'll talk about the main idea instead and you could implement it however you want.
The key idea to prevent XSRF is to store a random token in a place where code from other domains cannot access (such as a cookie). You could generate this token on server side and instruct the browser to store it locally for the entire session. (don't need to persist anything on server side)
Whenever you perform a request, send:
the token in your storage (if you use cookie, the browser will send it automatically).
the same token as the stored one in your request (whether as a header or in body using hidden field depending on how server code gets it)
On server side, the server will check for a match.
A sample code in jquery (with jquery cookie plugin):
$.ajax({
url:"someurl",
data:{token:$.cookie('token')}
});
The ability to read the cookie proves that this is from your domain, not external domains
There are various ways to implement this mechanism (don't need to stick to a specific solution) as long as they stick the the main idea:
Storing a secret token on browser in a place code from other domains cannot read it.
Send the secret token and the same token from browser to your server. The ability to send that same token proves that this is not a XSRF request.
How do I persist this value in order to be used for comparison?
We could store it as a cookie or as a session variable. Personally, I prefer cookie because:
Reduce memory consumption on server side.
We don't need to include that token in every generated HTML file in order for the browser to send it back.
Is there a difference in the set up for a synchronous form request
versus an AJAX request?
No, as long as you could prove this is not a XSRF request by sending the same token in the request. It does not matter where token is (a hidden field, a custom header,..). In case of Form, people usually send it as a hidden field.
Instead of using a cookie I'm using a JWT token which gets send with every request. Every request is a POST request so that the token does not get saved in the browser's history.
It's a single-page app.
The token looks like:
{
userId: 12345678,
expires: <UNIX timestamp>,
otherInfo: <something>
}
Everything is SSL secured.
The token is created on the server when the user logs on.
Would this be a good way to replace a cookie or do you see any flaws?
No, this is not a good solution. Using cookies (with a httpOnly flag) for cross-request persistence is not optional - it's the only way to safely store session credentials, in such a way that on-page JavaScript code cannot access it directly.
This is essential to prevent eg. session stealing in an XSS attack, by ensuring that scripts cannot access the credentials, but they can still be used in requests to the server.
Your use of JWT doesn't seem to really solve a problem, either - why can't you just use session cookies using an existing session implementation? This kind of thing is precisely is what they're made for.
I'm having trouble with passport.js using the local strategy. I have 2 specific problems:
I am not getting persistent sessions to work with example code (see
below) for the most basic case.
I want to go sessionless. For the
most basic case, on login, I'll pass in a username + password that
provides me with a session token, on regular requests I'll use this
session token hashed with some other stuff to authenticate. Is this
easily done with passport? It seems like passport doesn't offer much in this case and that cooking up my own solution is easier- just login/logout with standard checks, and then a middleware that unhashes request tokens to verify requests. Easy cheezy?
Problem 1:
Using the reference code from the library:
https://github.com/jaredhanson/passport-local/blob/master/examples/login/app.js
I do a series of commands to show logged out vs logged in:
A. check /account, not logged in
curl -v localhost:3000/account
As expected I get a redirect to /login
<p>Moved Temporarily. Redirecting to http://localhost:3000/login</p>
B. login
curl -v -d "username=bob&password=secret" http://127.0.0.1:3000/login
Also as expected, I get a redirect to /
<p>Moved Temporarily. Redirecting to http://127.0.0.1:3000/</p>
C. check /account, logged in
curl -v localhost:3000/account
What the hell???
<p>Moved Temporarily. Redirecting to http://localhost:3000/login</p>
In the case of 1, session support requires cookies to be configured on your server side and used by your user agent. Typically this is a browser, which will will transmit the cookies in each request, and the server uses them to restore your login state.
However, the curl commands you are using won't transmit cookies, so each request looks "new" to the server, which is why you see the redirect to login each time. I suspect if you try the same requests in a browser, this will work as expected.
As for 2, I'd need a few more details to suggest a good solution. If you are using HTML and web browsers to access your site, you're going to end up needing something like sessions. You could transmit this info in query parameters each time, rather than cookies, but you'll end up rebuilding a lot of what Express/Connect provides out of the box.
In any case, if you choose to go down that route, Passport provides a clean interface to implement your own authentication strategies. You'll simply need to parse the request for the relevant credentials and look up a user in your database.
API clients are different, and I'd suggest taking a look at Passport's OAuth support, which provides easy ways to authenticate access tokens that are associated with a specific client.
The problem isn't with passport, the curl command needs to store the cookie, so -c and -b parameters should be used to mimic browser behaviour. From curl manpage:
curl -b cookies.txt -c cookies.txt www.example.com
What this command does, is to store cookies in cookies.txt and send cookies reading them from cookies.txt - This is the way curl mimics netscape cookie-jar file format to write and read from.
As for your question per-se, Jared has already answered it!