I want to build a webapp that uses the wallet address as account, but yet I want to store the user in my db to allow specifying a nickname.
The problem I'm dealing with is that I want to call different apis, where the user needs to be authenticated / authorized in order to gain access .
Since the authentication happens 100% client side in my case (through the tronlink extension and TronWeb), I don't see another way as to add supplementary authentication for my webapp specifically.
If the user logs in to my app with a different password (not using the private key of the wallet), it seems like bad user experience as the user needs to authenticate twice (through Tronweb AND my webapp with a password).
How do you solve this problem?
It seems that the way to handle this is to foresee a separate login flow for the web app after all.
Even when the user already has logged in into Tronlink, it needs to obtain a token to authenticate rest calls.
The way it would appear to work is by generating a random nonce and storing this nonce along with the public key in the User table.
The login flow then consists of signing the nonce in the front-end, and verifying the signature in the backend after which the token will be generated and returned.
Related
I have created a website which allows the user to authenticate against oauth2 (from another provider), the basic flow is (assuming a new user):
The user loads my webpage
An OAuth request token key and secret is provided by the OAuth endpoint
I store the request token into the user's cookies
The user is redirected to the OAuth authentication page from an external provider
The user accepts and is redirected by to my webpage with URL parameters which specify the OAuth verifier and OAuth token
Using the request token (retrieved from cookies) and OAuth verifier (passed via URL parameters), I am able to get an access token key and secret from the OAuth endpoint.
I am now able to authenticate with the providers API and use that to get the logged in user ID.
I then store into a MySQL database, the user ID, a token which I generate as a random unsigned integer, OAuth token and OAuth secret. In cases of the token I generate already being in the database, I just continue in a loop until a unique token is generated. The MySQL database has a strong name, username and password. The database user can only access the table in question and only has privileges to add an entry, delete an entry and make a query.
I clear the request token from the user's cookies and instead store the user ID and my generated token.
When a user comes back to my website, I check if they have the user ID and token stored in their cookies, if so I attempt to look up the OAuth token and secret from MySQL. If they are found, I test they are still valid (does the API endpoint accept them) and if so, the user remains 'logged in' to my website. In cases where the user ID or token isn't found in MySQL or cases where it is found, but is not accepted by the endpoint (expired?), I just go back through the flow above.
The above all works correctly, new users can successfully authenticate, returning users find the website remembers them. I do not expose the OAuth token key or secret to the user and instead, give the user this token ID which I generate.
Are there any problems with what I am doing?
Should I be encrypting the OAuth token key and secret in my database?
Is there a problem with the fact if someone was to gain access to the token I generate, along with the user ID, they would be able to call my scripts. Is this a problem?
Should I be encrypting the user ID and token I generate before storing it in the user's cookies? Taking into account, ultimately whatever is stored in the user's cookies will get passed to my script, so if I were to encrypt, store to cookies, then next time read from cookies and decrypt, the user would still be able to access my endpoints by simply passing the encrypted version (assuming the server decrypts, if the client decrypts then the decryption key would be accessible via the users browser anyway), which doesn't immediately appear to offer any further security.
My goal is to tighten up the steps above so it is deemed robust and secure. The actual use case for my web site means it'll only have a tiny number of users (if any) using it. It was more of a learning process for me, combined with implementing something I actually need. But for the learning aspect alone, I would like to make everything sensible and secure. I am not trying to be overly pedantic and implement steps no other similar websites would implement, basically I would like my site to be secure enough that if there ever was a problem, no one could point a finger at me and say I didn't implement an adequate security system.
I have setup an web-based API to allow a remote app to GET/POST data. Every API call is authenticated with a User ID and Password that is encrypted with a secret key known only to the remote app and the website. This authentication not only ensures that the user can access the API, but also allows me to implement security features based on the user's profile (i.e. User A can see items A & B, but not item C).
I would like my server-side website pages to be able to call the same API methods remotely via AJAX calls, but, something just doesn't seem right about storing encrypted passwords in the code, and, my website implements a "Login As" feature, which will not allow me to set the encrypted password, since the passwords are not stored in plain text.
What is a good way to implement API security for both remote and "local" calls that doesn't require encrypting the user's password?
You should not be storing usernames and passwords in server side code. Sooner or later someone will lay eyes on your code and your data will be vulnerable.
But you should also not be storing secrets (key) in client side code. You should not assume your client can be trusted to keep that secret.
Giving user A access to item A and B, but not C is called authorization and depends on you knowing who calls your API (authentication).
You should probably look into a authentication protocol like OpenID Connect and an authorization protocol like OAuth 2.0.
Also see my answer to this question.
I'm trying to implement OAuth 2.0 for my API. I'm using a third party library to act as the basic OAuth provider, django-oauth2-provider,
and Tastypie as the framework. Those details shouldn't matter too much. The OAuth 2.0 works -- when a user is created, an OAuth 2 client
that manages the user's secret_key and their id is created. A customer can then supply the user ID they get back from the user creation
endpoint along with their username and password to get an access token which allows them to use API endpoints.·
Where I run into issues is retrieving the client id (which must be passed into requests for the access token). Obviously when a user is first created
I can return the client_id with the HTTP response. After that, however, there will obviously be cases where the user doesn't have their client id·
stored locally (this is a traditional user/app setup, not something like Google APIs where your client id is always visible). I want to protect
GET requests to the customer resource with OAuth, but that means I can't query the API for a given user's client ID. And it seems like the whole point
of OAuth is defeated if I can always just pass in a username and password to retrieve my client id from some oauth endpoint. Am I thinking about this wrong?
Also, from reading the OAuth specs I'm under the impression that a client id and client secret are all that should be supplied for getting granted an access token. Yet the implementation I'm using defaults to forcing the user to supply a client id, client secret, username, and password. I've overridden the implementation to require only the client id and secret, but I want to make sure that was the right call and I'm not missing something.
Edit for flup's response:
I'm dealing with a Django API as the resource server, and a user of an iPhone app as the resource owner. The iPhone app is directly associated with the server -- in other words, there are no third parties involved here and no plans to involve them in the future; all software is ours. I would think that the password flow would be what I would need in that case. Indeed, that seems to be what django-oauth2-provider supplies by default. I'd like to stay somewhat in line with what they are doing to not have to completely reinvent the wheel.
The goal of oauth2 is to let the resource owner give a client a valet key which authorizes it to access certain resources on your server on his behalf.
If there are no third parties involved, there is no client to authorize and no need to use oauth2.
Instead, you could use the standard authentication mechanisms present in tastypie.
From the posts about REST services, I see that it should not be used sessions together with REST, and with every request there is need to send user credentials to the REST service. But I don't see that somebody continues then how to make the authorization in next requests after login.
In my project, I authenticate (login) the user, checking his credentials from database server.
If with every REST request also comes user credentials again, does this mean that, for any need of authorization after login, I need to check the credentials again from the database?
This means, after login, with almost every click and surfing pages, I need to access to the database to check the user credentials, just like I do it for login.
Or...
Am I missing some thing?
Is there another way to remember in the server side that the user had already logged in before and thus is authorised?
Do I keep some secret key related to the user in the server, and then check this etc.? But, does not this mean keeping a session?
REST => Not Session => Send credentials with every request
Does the above mean, => Authorize the user just like in the authentication ?
Or what are other alternatives?
Thank you for clarifications.
I think that this is the best approach:
REST => Not Session => Send credentials with every request
Take a look on OAuth. The version 1.0 may be useful for you.
Spring Security already have implementations for OAuth in Java.
If with every REST request also comes user credentials again, does this mean that, for any need of authorization after login, I need to check the credentials again from the database?
You have to authenticate user on each request, but whether authentication uses database or not depends on implementation. By the way, you also have to then authorize the request for the authenticated user.
Do I keep some secret key related to the user in the server, and then check this etc.? But, does not this mean keeping a session?
You can have some secret key known only to the user as an alternative to username-password pair and use this secret key for authentication.
The presence of a secret key doesn't mean keeping a session, because it is not necessarily change on a per session basis.
In my project, I authenticate (login) the user, checking his credentials from database server.
Login is not authentication, it's usually a request for a secret key / session key done using username-password pair for authentication
I have a web application that needs to allow users using different webclients (browser, native mobile app, etc) to register. After signing in they can access restricted content or their own content (like entries they create, etc).
What I did so far: I created a jax-rs rest webservice (I'm hosting my application on glassfish) that exposes the following methods:
register - user POST's his desired username/password/email/etc; if username/email is unique, an entry for this user is created in the database (I'm using Hibernate for persistence)
login - user POST's username and password. If they are ok a UUID is created and returned to the user (this will be used as a token for future requests). I have a table called logedusers, with userID, token, validSince as columns.
Here is where it gets confusing for me.
Let's say that I have another method, getUserEntries, that should return all the entries made by the user. To make this clearer, there will be a Entry table with the following fields: entryId, userId, text.
What is the best approach here?
What i do now, is I make a get request and pass in the token like this:
localhost:8080/myApp/getUserEntries?token=erf34c34
Afterwards, if the token is valid, I get the userID from the logedusers table and based on that userId, get all the entries and return them as json.
Something like this:
#GET
#Path("getUserEntries")
#Produces(MediaType.APPLICATION_JSON)
public Response getUserEntries(#QueryParam("token") String token) {
String userId=getUserIdFromToken(token);
if (userId == null){
return Response.status(Response.Status.UNAUTHORIZED).build();
} else {
//get some data associated with that userId, put it in the response object and send it back
return Response.ok().entity(response).build();
}
}
However, what happens if I have more methods that provide data if they are called by a valid user?
I'd have to do this check at the beginning of every method.
I want to make this authorization process transparent
So, two major questions here:
Is this design ok? The whole authenticate with user/pass, server creates and stores and sends token to the user, user sends token on future requests.
What do I do if i have many endpoints that need to determine the identity of the calling user? Can I mark them with some annotations, use some sort of security provider / authenticator (where I can add my own logic for validating - eg check to see if the token isn't older than 5 days, etc).
Thanks
Is this design ok? The whole authenticate with user/pass, server creates and stores and sends token to the user, user sends token on future requests.
It's somewhat OK. The conceptual level isn't too bad (provided you're OK with self-registration at all) but the interface needs a lot of tweaking. While yes, POST to register and login is correct, for the rest of your webapp you should be pulling the identity information out of the context if you need it, and using role-based access control at the method level where you can.
Note that your container has a whole set of authentication and authorization-support mechanisms built in. Use them.
What do I do if i have many endpoints that need to determine the identity of the calling user? Can I mark them with some annotations, use some sort of security provider / authenticator (where I can add my own logic for validating - eg check to see if the token isn't older than 5 days, etc).
Do they need the identity? Or do they just need to know that the user is allowed to access them? If the latter, the easiest method is to put a suitable #RolesAllowed annotation on the method, at which point (with suitable configuration; see the JEE5 security docs). If the former, you need to get the HttpServletRequest object for the current action and call its getUserPrincipal() method to get the user's identity (or null if they've not logged in yet). This SO question describes how to go about getting the request object; there are a few possible ways to do it but I recommend injection via a #Resource annotation.
What I wouldn't do is allow users to normally provide their own identity via a #QueryParam; that's just wildly open to abuse. You can allow them to ask about other users that way, but then you need to decide whether you are going to tell them anything or not based on whether the current user is permitted to know anything about the other user. That's the sort of complex security problem that comes up in a real app, and is a good point for needing the current verified user identity.