Pubnub Auth Key and Auth Key Safety (Grant Token) - websocket

I have stuck in here and couldn't find a solid solution.
I use PHP in server-side and Vanilla JS in the client side.
In server-side, I'm generating a auth token (https://www.pubnub.com/docs/general/basics/manage-access) for current logged in user's channel to make him able to read his channel messsages by the following code:
I'm also generating a new one when the key timeout so all OK with the generation.
But my problem is starts here:
I'm passing the key into the client like this:
And user is getting access to the channel. But the thing is, I'm passing this auth key to the client-side. Which is someone that get this user's auth token; can setup their own client and can read messages that sent to this user.
How can I deal with that?
And another one:
I'm publishing to a channel in PHP like this. But I'm able do to that without setting auth token. I'm sure auth token system is working because when I pass wrong auth key to the client it's giving 403 forbidden. But however, I'm able to publish to channel without auth key in here. Is this because it's server-side?
Thanks!
Googled everything...

someone that get this user's auth token; can setup their own client and can read messages that sent to this user
This authorization strategy is the same as JWT. How will someone get this auth token? If you are using a secure connection to your server (TSL, aka https), and your PHP server is secured, then that is all you can do. This is the internet :)
Now how secure is the end user's machine? Are they susceptible to phishing or other schemes that might allow a hacker to gain access to their machine? Humans are the easiest thing to hack and you can't really do anything to secure them ;)
So as far as PubNub is concerned with security, you are doing exactly what very large companies have been doing for over 10 years with PubNub. The question is how secure is your server that a hacker can't get access to your code and data and get your PubNub secret key. In my 9+ years at PubNub, I've never known this to happen.
granting permissions on your channel
You are granting too many permissions but it doesn't have any negative side effects.
read - subscribe (receive messages), fetch (messages from history), and some presence stuff (get/set state, here now)
write - publish (send messages)
get and set - this is for PubNub Objects only which is different than pub/sub.
Again, no harm comes from granting permissions that have no effect on the resources you are granting to but it adds to the size of the auth token (just a little bit in this case).
able do to that without setting auth token
When you do setToken you are setting that on the pubnub object that you use to invoke PubNub operations. The PubNUb SDK automatically adds the auth token as a query parameter in the request. So it is being passed automatically for you.
Open your browser console, select the Network tab, and look at any PubNub request/url. You will see the query parameter names auth and the value is your auth token.
PubNub Secret Key give you all access
The secret key gives your server the ability to grant permissions (generate an auth token) AND it gives your server all access to all things in your PubNub key set. Don't let that secret key get compromised.

Related

Is this a secure authentication flow (with Auth0 and SvelteKit)?

As there is currently no Auth0 SDK for SvelteKit, I am learning (or at least trying to learn) far more about authentication than I originally intended when setting out to incorporate Auth0 into my SvelteKit app (including server side authentication). The documentation is a little confusing (or maybe it is just massive, or maybe I am just not that bright), so I was hoping to describe my auth flow here for critique (in the hope that this will be helpful to others in the future).
I have reviewed this great post about SPA auth as well as Auth0's educational offerings. Still I am not sure I am connecting the dots properly. Here is my flow. All of this occurs over SSL only.
I create an Auth0 client on the client side using their client SDK (#auth0/auth0-spa-js). That client performs authentication via the Auth0 popup.
Once authenticated, everything works as expected on the client side. But if I want to control access to routes on the server side, I need to get information back to the server. So...
After authenticating, Auth0 creates an ID token (a signed JWT) which is stored in the browser's local storage. I save it as a session cookie (with SameSite=strict; HTTPOnly; Secure; options set) so that it gets passed back to the server with requests for route authorization.
So let me pause right here...I understand that (at least according to some including the Auth0 educational video linked above) the ID token is not supposed to be used for authentication and should never be passed around. That is what an access token is for. However, in this scenario where the exchange is all first party (my client, my server), it is my understanding that it is "ok".
However, it does make me nervous that the Auth0 SDK is not setting the cookie itself. This makes me wonder if I am Doing It Wrong™.
On the server I validate the id_token using a public key, and can then save user details, etc. on the backend if I wish, and allow access to appropriate routes (via hooks.server.js in the case of my SvelteKit app).
When the user logs out, or if the token expires, the cookie is removed.
(As a side note, I have yet to figure out how to refresh the ID token when it expires as the Auth0 client SDK does not seem to ever update the ID token in the browser storage even if it is expired.)
Is that a secure and typical way of going about it?
(For a work in progress working example, see my svelteauth0 repo.)

Open ID Connect Session Management Access/Refresh Token vs Session iFrame

We have a web app in which we allow users to log into the app using any Open ID provider(e.g. Okta, Google, Facebook etc.). We want to implement the correct Open ID Connect prescribed methodology/workflow to keep the user logged into the site.
The existing implementation, looks at the expiry of the Access Token then if it's close to expiry uses a Refresh Token to get a new Access Token to keep the user logged in. I feel like this is wrong. When a user logs in to the web app, the Identity Token is used to Authenticate the identity of the user using the Authorization Code workflow. The Access Token and Refresh Token are stored on the server side. Periodically, the Refresh Token is used to get new Access Tokens to keep the user logged into the site. I believe this is a security risk because -
Imagine if a user is logged onto his OP account in a browser. He opens up Sky and is directly logged into MP because he’s already logged into MP. He then in a separate tab, logs out of his OP account. He will continue to be logged into MP for days on the basis of this Refresh Token/Access Token mechanism! Isn’t this a security risk?
If feel like the correct way to go about this is to use Session Management using iframes as prescribed here on OIDC -
https://openid.net/specs/openid-connect-session-1_0.html
For more context, when a user logs into our WebApp we pull data from the OP's UserInfo endpoint to create a profile within our WebApp and set permissions/roles within our app based on data sent over from the OP's UserInfo endpoint. We continue doing this periodically. For this purpose, I feel like using the Access Token(and using the Refresh Token to get new Access Token) to access the UserInfo API is correct because it conforms to the OAuth 2.0 concept of protecting/authorizing API/Resource endpoints using Access Tokens.
I want to know if this is indeed the correct way to manage how a user should be logged in when supporting Open ID Connect.
I think the first question is whether you want to bind the lifetime of an OpenID Connect provider Single Sign On session with the session of your application. You just want to authenticate a user using their OpenID Connect service. If I logout of Google, I expect to be logged out of GMail, but not a third-party application that used Google for authentication. Would you like to implement Single Sign Out as well?
But if I wanted to be logged out when you logout of the OpenID Connect provider, I would implement the OpenID Connect Session management. There is one thing good to be aware of when using iframes and cookies - browsers have an option to "Block third-party cookies" (that's how Chrome calls it), it's turned off by default, but as far as I know, it disables the SSO functionality when turned on.
I'm not sure why you request the userinfo endpoint periodically. If you just want to check whether the access token is still valid, you could also use the token introspection endpoint.
For security concerns, I would suggest you to read the OAuth 2.0 for Browser-Based Apps RFC. It recommends using the auth code flow with PKCE instead of the implicit flow. With the implicit flow, access tokens transported in redirect URLs stay in network and browser caches and can be used right away by an attacker. The auth code with PKCE needs a code_verifier (one-time secret) in order to be exchanged for tokens. So I would first check how the providers work with a configuration you choose and if it's even supported.

JWT Token Security

As JWT tokens are sent over the headers to authenticate uses, a user can just inspect the web call in chrome dev tools and copy paste the token and use it to access the exposed API.
For example, if I am using this token to create a record, a malicious user can use the same token (by using the above mentioned way) to create a new record in Database.
How can I stop this from happening? Is using Token Encryption with public key of server the way to stop this?
Token represents user identity. It is normal, that user can view his own token.
Token is validated on the server. Normally there is is no easy way to fake a token. Use cannot generate a new token on his own.
Communication between browser and server should be done via TLS. Then no third party will be able to see the token.
If your user gives access to his browser to somebody else, then yes, the other person can potentially access the token and used it later on on another computer, it this token is not expired yet. But this is not specific to the token, this is like giving access to your password to smb else.
Several steps can be taken as given below:
You should use https connection instead of http connection. This will encrypt your message which is sent to server or received from server. So if a man in the middle catches your packet, he can't do anything because message is encrypted.
Also add a short time validity for jwt token depending your app behavior.
Add an appropriate key size for your self-signed token validation. AES keys shorter than 128 bits, or RSA keys shorter than 1024 bits for legacy apps.2048 bits encryption now a days popular.
HSM (Hardware Security Module) can be introduce for signing and encryption task while key are not accessible from OS or software level.
You should be digging deep for more here[cheat sheet for jwt token OWASP].

Killing "session" with SignalR, OWIN, and Web API

It has been a long road but I have SignalR working with my Web API which uses OWIN for token authentication.
I have a mechanism where if a user authenticates on terminal #1 and then later authenticates on terminal #2, I can send them a Javascript alert saying "Hey, only one session at a time. Which one do you want to log out?"
The question I have is how to kill their "session" on one of the terminals? I say "session", but since this is a REST based API there really is no session. If I could force them to re-authenticate on the terminal they choose to "log out" from that would be sufficient.
I have the SignalR connectionId of each client. Is there a way I can expire their authentication token and force a logout?
Note - The client is separate from the Web API in that they are hosted on two different servers. The client is just HTML/Javascript making calls to the Web API.
If you are using a bearer token approach, and you are not storing tokens (or token hashes) into some kind of persistent storage (e.g. a DB), then you have no way to invalidate a token.
Since OAuth is not an Authentication protocol, it do not have any kind of log out concept in it. Your only option is to remove the token from the client storage (I can imagine it is stored inside the localStorage or in a cookie).
Of course this does not really invalidate anything, and if the token is not deleted for some reason, it can still be used for authorization purposes.
Your only option, if you really need a single access token valid at a single time, is to store some information about it in a database, and check that storage every time you validate the token. You could, for instance, store the hash of the token (never store the real token for this reason, they have the same value of passwords once stored) with the username, but please note that this approach makes your authorization protocol a little less stateless than before.

Using JWT to implement Authentication on Asp.net web API

I have been reading about JWT.
But from what I read it is not an authentication mechanism but more like a crucial component in a Authentication mechanism.
I have currently implemented a solution which works, but it was just to try out JWT and see how it works. But what I am after now is how one should make use of it. From my experience of it its basically just an encryption mechanism that gives you a unique encrypted key. You are also able to put information inside of this token.
I am wanting to implement it in terms on a ASP.NET web api 2 to be consumed by a mobile application.
So step 1:
app => Server : Login (user, pasword)
Server => app : Login OK, heres your JWT
app => server : Get my profile (sends JWT with request)
Server then decrypts JWT and determines the requests Identity.
Now this is just my understanding of it, Look I could be on the totally wrong path.
Is the Ideal of JWT so that you dont have to authenticate on every request? I just authenticate the users credentials once (on the initial login) and there on after the server can simply use JWT and no have to lookup the users pw and user in the DB?
I just want to use the JWT to Identity who the user is. I will then authorize then after i have authenticated them. As I know there is a big confused with the new MVC and Authentication and Authorization.
So what my question comes down to.
How can I safely and effectively Implement a Authentication Mechanism Using JWT?
I don't want to just cough something up that seems to work and not have any Idea of the security implications. I am sure that there exists a source some where that has possibly designed a secure mechanism that would suit my requirements.
My requirements are:
Must only have to check db for users credentials once off per session? Due to the use of bcrypt using a lot of resources to compare passwords.
Must be able to identify the user from their request. (I.e who they are, userId will be sufficient) and preferably without accessing the DB as well
Should be as low overhead as possible, with regards to resources on the server side processing the request.
If an intruder had to copy a devices previous request, then he should not be able to access the real users data. (obviously)
Thanks
Your understanding of JWTs is good. But here are a couple corrections and some recommendations.
Authentication and Authorization
JWTs have nothing to do with authentication. Hitting your DB and hashing passwords only happens when you authenticate on creation of the JWT. This is orthogonal to JWTs and you can do that in any way you like. I personally like Membership Reboot, which also has a good example of using JWTs.
Theoretically, you could have the user enter a password once a year and have the JWT be valid that entire year. This most likely not the best solution, if the JWT gets stolen at any point the users resources would be compromised.
Encryption
Tokens can, but don't have to be encrypted. Encrypting your tokens will increase the complexity of your system and amount of computation your server needs to read the JWTs. This might be important if you require that no one is able to read the token when it is at rest.
Tokens are always cryptographically signed by the issuer to ensure their integrity. Meaning they cannot be tampered with by the user or a third party.
Claims
Your JWTs can contain any information you want. The users name, birthdate, email, etc. You do this with claims based authorization. You then just tell your provider to make a JWT with these claims from the Claims Principle. The following code is from that Membership Reboot example and it shows you how this is done.
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var svc = context.OwinContext.Environment.GetUserAccountService<UserAccount>();
UserAccount user;
if (svc.Authenticate("users", context.UserName, context.Password, out user))
{
var claims = user.GetAllClaims();
var id = new System.Security.Claims.ClaimsIdentity(claims, "MembershipReboot");
context.Validated(id);
}
return base.GrantResourceOwnerCredentials(context);
}
This allows you to control with precision whom is accessing your resources, all without hitting your processor intensive authentication service.
Implementation
A very easy way to implement a Token provider is to use Microsoft's OAuth Authorization Server in your WebAPI project. It give you the bare bones of what you need to make a OAuth server for your API.
You could also look into Thinktecture's Identity Server which would give you much easier control over users. For instance, you can easily implement refresh tokens with identity server where the user is authenticated once and then for a certain amount of time (maybe a month) they can continue getting short lived JWTs from the Identity Server. The refresh tokens are good because they can be revoked, whereas JWTs cannot. The downside of this solution is that you need to set up another server or two to host the Identity service.
To deal with your last point, that an intruder should not be able to copy the last request to get access to a resource, you must use SSL at a bare minimum. This will protect the token in transport.
If you are protecting something extremely sensitive, you should keep the token lifetime to a very short window of time. If you are protecting something less sensitive, you could make the lifetime longer. The longer the token if valid, the larger the window of time a attacker will have to impersonate the authenticated user if the user's machine is compromised.
I've written detailed blog post about configuring the OWIN Authorization server to issue signed JSON Web Tokens instead of default token. So the resource servers (Audience) can register with the Authorization server, and then they can use the JWT tokens issued by Token issuer party without the need to unify machineKey values between all parties. You can read the post JSON Web Token in ASP.NET Web API 2 using Owin
For the formal concept . The Authentication is the process of verifying who a user is, while authorization is the process of verifying what they have access to.
Let’s see the real life example
Imagine that your neighbor has asked you to feed his pets while he is away. In this example, you have the authorization to access the kitchen and open the cupboard storing the pet food. However, you can’t go into your neighbor’s bedroom as he did not explicitly permit you to do so. Even though you had the right to enter the house (authentication), your neighbor only allowed you access to certain areas (authorization).
For more detailed and for users who like more STEP BY STEP implementation on practical use of JSON Web Token in WEB API. This is must read post Secure WebAPI Using JSON WEB TOKEN
Updated to use: System.IdentityModel.Tokens.Jwt -Version 5.1.4

Resources