Designing login module in client rich/AJAX based applications - html

I am working on an Angular application.
We have a web service which takes login credentials and returns an apikey if the credentials are valid.
On the client side we make an AJAX call and if the credentials are valid we are storing the API key in session storage and taking the user to home screen.
Also we have a route guard to secure all screens with authentication.
Now when we try to open a link in new tab, the user is again taken to login screen because the API key is in session storage.
We can use local storage to store the API key, but the problem here is the API key never expires but is available to all tabs.
Can anyone please suggest a better solution?
A solution which I think will work but did not try is, make a normal HTTP request is when the user clicks login, then create a session on the server side and redirect the user to home page from the servlet. In the client side, add a web service call in ngOnInit to see if the user is logged or not.

Related

Login Security using jsonwebtoken

I am currently working on a website using React where I want to be able to have user login. Right now my strategy is to send form data to the server (express) on submit, and if the info matches a user in my DB, the server sends back a signed JWT with no sensitive information (just the username).
Once the client receives the JWT, I am adding it to localStorage as well as adding the decoded data of it to my redux store. I plan to have my redux store holding the currently logged in user.
I believe there may be a security issue in my site because currently I have it so when the user first arrives at the site, If there is a JWT, it is added to my axios headers and the decoded JWT is set to be the current user. The code looks like this:
if(localStorage.jwtToken) { // If token present, most likely a user is signed in
setAuthorizationToken(localStorage.jwtToken) // Set that token to head all api calls
store.dispatch(setCurrentUser(jwt.decode(localStorage.jwtToken))) // Set user in redux store
}
Currently I've found that if someone just goes into my localStorage, copies my JWT and adds it to their localStorage then bam, they are me. I'm unsure if this is really a security flaw because the only way I've recreated this myself is by physically copying the token from one browser to another. But in general this seems very unsafe that just taking my token steals my identity.
If anyone knows a way to make this more secure or if there is a better strategy, or at least tell me what I'm doing wrong that would be highly appreciated.
How can another person get your token? Give expire time to token needed. Maybe try different way for securing token, especially give more security in API side. When logging in, store log activity in database and create unique field to identificate it such ip address or user-agent, or maybe detect is that user have been hit login endpoint before or not.

Is possible to create a JSON RESTful OAuth2 server?

The part where user needs to enter their creds can also be shown if the client app redirects to a stateless static page alongwith the some params, that belongs to the oauth-server.com domain so that no other app has access to username and pwd.
After POST -ing this form to oauth-server.com, Is there a way to redirect the user back to the client app without the oauth-server redirecting via a browser session? Is there a json restful mechanism to OAUTH2?
So to answer your question, redirect_uri exists for the sole purpose of letting the client app(web, iOS or android) know status of the authentication request.
And OAuth2 server cannot do anything other than redirecting, because where the server will redirect to? (which is what redirect_uri anyways).
Refer the following articles for best practices to redirect data to installed / mobile client app
https://developers.google.com/identity/protocols/OAuth2InstalledApp
specifically this section,
https://developers.google.com/identity/protocols/OAuth2InstalledApp#choosingredirecturi
Hope that helps!

Correct HATEOAS response when creating a user account

I have a REST api written in node which uses HATEOAS. The user is required to have an account before they can access the bulk of it.
They register an account with login details, then login to obtain an access token, and then use that token in order to access any endpoints that aren't register or login.
Issuing a get to the root responds with a directory with available actions.
Q: What is the correct response from register, to tell the client what it can do next (i.e. login)?
register technically creates a new resource on the server so a 201 CREATED and a Location header would seem appopriate. However the login reference isn't the location of the newly created resource.
Should I return 201 Created with a Location pointing to the newly created user (e.g. /myaccount or /users/{id} and then include a login link in the response body?
{
_links: {
self: { href: "what goes here?" },
x:login: { href: "/login" }
}
}
Do I not tell the client at all, and require them to do a get on the application root in order to fetch a list of available endpoints. This should include login anyway. Assuming the client had to do that in the first place to get the register link it should already have login.
Expecting the client already to already have the login link feels uncomfortable as it relies on an assumption of the client's prior activity.
Requiring the client to issue another request to the root directory after registering seems mean, inefficient and unnecessary. If the client has just created a resource it seems only fair that the server should respond with what it can do with it next.
I like to have my api's act no differently than a webpage. If you want the UX of your application to be the user is taken to login after they register, then 302 them from a successful register to the login resource. And upon successful login, 302 to them to the appropriate destination (IE, if they tried to access something with no token, then take them to login, with a destination of the original requested resource). That's and important part to your #3. Having a link off the root that leads to login, but you need to protect all the other links such that they indicate (and link to) a login being required to access the resource. The client app should expect to get this login required response at any time as tokens can (and do) expire at any time.
Following on this, it might make sense to do the JWT as a cookie instead of as an Authorization Header, it would make it a bit easier for the client (they just have to setup a cookie jar)..if the client is say a native mobile app that maintains a single connection setup. If it's server to server, then auth header makes sense. I'd go about supporting both to cover both scenarios.
Continuing on the idea of thinking of the api as a web site. Why have them login after registration at all? Why not have the registering of an account end up with the login token being sent? they just set their user/pass, why make them enter it again? I realize with some more exotic architectures the register service can not perform the login action (perhaps it doesn't have the private key to sign the token), but if it is possible i'd consider it.
If you really want to stick to the 201 header (which is fine, just make sure the docs of your register relationship indicate that), then option 2 is the closest in my opinion. A location header to the URL of the account just created a 201 is pretty standard for creating a user. But, i'd not return what you've supposed there. You're kind of returning a account-created resource (the thing with the login link), but do you really need this custom resource? If you want to give some messaging back to the client (like "Account Created") in that resource then absolutely yes, but you could also just give them back the root resource.
tl;dr; Decide what you want your UX to be and then make your API implement your UX.

Secure iOS to online database connection

I have an iPhone application that needs to collect data from an online MySQL database. I've written a PHP web service so I collect the data with JSON. The problem is that everyone can see the data if they go to the URL now. How do i secure the data transfer properly?
Thanks for your suggestions.
Typically, if you are showing data private to a particular user, then each user will generally have an account (user id and password). The app will pass the user's credentials to the server before the server will provide the user's data.
You can also do something similar using SSO integration, or OAuth (ala Facebook).
In some cases, your app may only pass the username/password on the initial call and receive a session ID, which the app passes on remaining calls. This allows the server to store session data.
Even if the data isn't private to a particular user, you can use accounts to restrict access and privileges for a publicly reachable web API.
In all of the above cases encryption such as SSL (HTTPS) must be used to protect the authentication mechanisms and data transfer.
I'm assuming your data is public for all users of your app, in other words, you don't want to implement a login mechanism for your users. If you just want to make sure you return the data only to users of your app and not to anyone who happens to enter the right URL in their browser, you will need to sign your requests, so that only requests from your app are accepted by your server.
I use a secret key that my app uses to create a hash/digest of the request which the server verifies (it knows the secret key as well). Also I make sure requests cannot be replayed if they are intercepted by adding a timestamp and a nonce. The timestamp is checked to be within 10 minutes of the server's timestamp (relaxed sync) and the nonce must be unique (server keeps the last 10 minutes of nonces). This way no-one can copy the same request, the server will just serve an error if they try.
This post explains how to sign your requests in a bit more detail:
http://www.naildrivin5.com/blog/2008/04/21/rest-security-signing-requests-with-secret-key-but-does-it-work.html

box.com api OAuth authentication

Either I'm dense, or the docs assume I already know what they're telling me, but I need some clarification on doing authentication for a box.com app. I really don't understand whate's going on. As I read it:
the app running on the user's machine sends a request to Box, including all the little secrets (Which aren't all that secret any more if the user knows how to read the code).
The user is directed to the Box login page, which then sends the user to my server (with no page specified) attaching an authentication code.
The app somehow magically gets that code back from my server and sends a request to Box for the access token.
Box sends the access token to my server?
The app again magically gets the access token from my server and sends its APT requests.
Obviously I got lost somewhere.
And, why do I have to have a server involved in the process? The article on making a JavaScript app refers to a direct request for a token. Is there documentation on that somewhere?
You register your application on Box
After registration you receive clientId and clientSecret once on Box website
You hardcode your credentials somewhere in your application
First time your application needs to access Box API it should redirect user to https://www.box.com/api/oauth2/authorize, specifying your clientId, clientSecret and redirectURI as parameters. About redirectURI see below.
The box.com website opens. User enters his own credentials in the web form on box.com
User allows your application to access his files via API on the box.com website
Box redirects user back to you application using redirectURI specified before. One of the parameters to this request is "code". This is a very short-lived (30 seconds) access code that is only aligable for obtaining real access token.
During next 30 seconds your application should make another call to Box API to next URL: https://www.box.com/api/oauth2/token, specifying the previously obtained code. If everything was correct, your application receives an access_token, a refresh_token and "expires" values.
Now your application can make requests to Box API, specifying access_token every time
access_token expires in number of seconds, specified in "expires" field. It should be about 3600 seconds or 1 hour. Each time your application sees that access_token has expired, it should make another request to Box with the refresh_token and obtain a fresh access_token for another 1 hour.
refresh_token itself expires in 14 days
Note: if you develop a desktop application, then you should open browser for user on the step 4, redirectURI should be something like http://127.0.0.1:8080/Callback and you should run a small webserver just to catch the redirect with the code as in step 7.
Box requires that you specify a redirect_uri in your application's profile, and it must be an HTTPS URL.
As a result, it is not possible to use box with what google's oauth2 documentation calls "Client Side" or "Installed" applications, only "Web Server Applications" are allowed. Web Server applications do not have the secret leaking problem, because only the server knows the secret. You can pass the access token from your server to javascript on the client after
the oauth transaction is complete, if you want the client to make api requests directly.
In your question you are not totally clear in what you are actually trying to produce.
I however suspect that you are trying to write a client application what needs to authenticate to box using the OAUTH2 solution they have delivered in API V2.
If this is for an IPhone for example BOX has a great example of how to handle it.
In a WinForm application you would need to capture the resulting code sent back by box in the browser1.isnavigating event.
Windows console application you register a custom URI registration to collect the code.
Neither of these need to be registered in the API developers Application on box as you would pass the redirect required in the request to box.
If this does not point you in the right direction and your writing a .NET app then post again and I will try to clarify a little more.
Box requires some form user interaction which is short sighted in my opinion but try a web service that simulates a user interaction which then you can save/pass the token to your application to sync up with the Box "Cloud".