How to get a unique username - java

I'm looking to use Google's App Engine (Java) to provide the backend to an Android messaging app I'm currently writing, I'm just starting out with GAP but have a little experience with Java (through Android).
The first time someone uses the app it will send some sign-up data to the server, this will stored in the GAE datastore, and a unique id returned to the phone (or an error message if something broken).
As I can't see something that looks like key = datastore.giveMeAUniqueKey or datastore.hasThisBeenUsedBefore(key) I guess I'm going to have to generate a random key and see if it's been taken (I'm not that sure how to do that to be honest).
Any ideas (either answers to the specific question, or pointer to useful "getting started" resources)?
Thanks.

If this value is not security sensitive (ie, it's just a user ID and you have some other method to authenticate the phone), just do an insert and take the key of the newly inserted entity. The datastore will assign a guarenteed-unique key automatically if you insert a new entity without providing one. Alternately, you can explicitly request an ID with the allocate_ids call.
If the value is security sensitive (it's a session nonce or something used for authentication), use the SecureRandom class to generate a sequence of random bytes. Do not use this as a key for an entity such as a user object; this would preclude changing the session ID if the user's session is compromised. Have a separate user ID used for that purpose, and use this secure nonce only for the authentication step.
Note that simply looping creating IDs, testing for conflicts, and inserting is not safe without using a transaction; it's easier (and faster, and cheaper...) just to use app engine's built in ID assignment system.

Related

Should you expose a primary key in REST API URLs?

I'm very new to Spring. I'm trying to create a REST API using Spring Boot and I'm stuck whether to expose my user's primary key or not which also happens to be their email. Something like api/user/example#gmail.com. A big part of me says it's okay since it would sensible to expose it as it is the identifier for that specific record when viewing, deleting, and updating. Is there a security risk for this? What is the best practice for such implementation? Right now I'm combining the #PathVariable and #RequestBody. I didn't like the idea of putting my primary key in the RequestBody thinking that it might pose a risk...or is there?
#RequestMapping(value = "/updateUser/{customerEmail}", method = RequestMethod.POST)
public ApiResult updateCustomer(#RequestBody UserDetailsDto userDetailsDto, #PathVariable String customerEmail) {
//service call...
}
First of all, user e-mail is often considered to be PII (Personally Identifiable Information). As such it would be unwise to put it into a URL, because you should not put any sensitive information into the URL. Header - ok, body - too. But not into the URL. The reason is, that all the proxies/load balancers/other infrastructure you have or might have in the future will always be allowed to log URLs for debug reasons. And you don't want your sensitive data to leak across the components like this. No company policy would ever allow that.
Spring is a good framework of choice, usually as long as the identifier is unique it should be fine, the problem with using an email is you are exposing your users data more easily which could be problematic to the users, I would suggest you rather use a string of unique characters as an identifier in the form of:
http://api.example.com/user-management/users/{id} as an example http://api.example.com/user-management/users/22
in this case identifier of user 22 has the email example#gmail.com in this way you are not exposing sensitive data when doing an update here is a link that gives guidance on best naming practice https://restfulapi.net/resource-naming/.
Another tip given in the link provided is to avoid using URI's as CRUD (Create, Read, Update, Delete) functionality "URIs should be used to uniquely identify resources and not any action upon them".
Any sensitive information (in this case email but in other case that could also be your database autoincremented primary key field ID in your table) should not be exposed.
Once way to go around that that I know and I use is to have 2 fields. For example, I have table USER {ID, USERID, NAME, ...}
Above, ID is autoincremented Long field representing PK.
USERID on the other hand, is a field generated of random characters or GUID which I use to pass back and fort in REST calls.
So, I might have record in USER table as:
USER {1, "a23asf60asdaare998700asdfasr70po097", "Mike", ...}
If I were to pass ID=1 back and forth, a malicious user could easily deduce what it is and how to query next user. For that reason, i pass USERID which represent a public and safe version of ID that can be passed and no one can know what would be the USERID of next user.
So, your response model, dto model etc should have these fields and response model should return USERID instead of returning ID. And you can use JPA to find the user by the USERID (so, based on that, that method must be called in this case findByUserId).
The same would apply for your case where you use email instead of ID if you want dont want to expose user emails which make sense to me.
Hope that helps.
I think it's more a matter of taste and personal beliefs rather than objective aspects.
Since HTTPS is more or less mandatory today, it's a lot harder to obtain the e-mail address by just sniffing with a tool like Wireshark.
So what's the possible risk? Since users have to be authorized to call this endpoint, they know at least their own e-mail address and most likely used it to authenticate. So a user can't modify or acquire the data of another user, if properly implemented.
A problem which may be of concern is that it might be possible to check for a registered e-mail during the registration process. Depending on what kind of application you're developing, this might be an issue. To give a brief example of such a case: Imagine a catholic priest registered on a porn site or the e-mail address of your husband/wife registered on a dating platform.
So may advice: Force HTTPS and you are pretty fine to use them as a primary key. However, if you have the possibility to abstract this, I'd do so. A numerical key or username may be a better choice and also easier to handle - but it makes no difference. Imagine if you have an endpoint to acquire the user's data, including e-mail address. It just doesn't matter if you acquire this data by a numerical key or by the e-mail address. In the end, you end up with the e-mail address in the response's body. And if this body is accessible by someone, he can also access the username and password, thus rendering any security measurement you've taken useless.

Best Practice on Parse Server Security

I am actually trying to write a small App where I intend to store the Names and Surnames of users in a Parse Server data base. I would need , for a define user , to read and get the Name and Surname of other users at some point.
I have read that anyone can decompile my APK and extract the App id and the Master Key . For me these values are stored in strings.xml , but I can't understand how I can store them elsewhere , as they are needed to connect to the server.
Is there a way to protect the decompiling in order to preserve the MasterKey? Or should I enforce ACL for those columns (Name and Surname added in the User class) and like read the Name and Surname of other users using Cloud Coud when I need it?
What would be the best practice to do that please?
DO NOT USE MASTER KEY IN A CLIENT APP
If your master key is compromised then your whole parse instance will be compromised. Instead, use class and object ACL to protect your data. If you need special queries that require master key, do it in server-side or cloud code.
Read this doc carefully: https://docs.parseplatform.org/android/guide/#security
There are some universal solution for "protect things inside APK".
Google APK reinforcement.

Where is allocateIds in the Google Cloud Datastore java library?

I moving some data from Mysql to the Datastore and for this data migaration I want to keep the old Ids from Mysql.
I found this note here
Instead of using key name strings or generating numeric IDs automatically, advanced applications may sometimes wish to assign their own numeric IDs manually to the entities they create. Be aware, however, that there is nothing to prevent Datastore from assigning one of your manual numeric IDs to another entity. The only way to avoid such conflicts is to have your application obtain a block of IDs with the allocateIds() method. Cloud Datastore's automatic ID generator will keep track of IDs that have been allocated with these methods and will avoid reusing them for another entity, so you can safely use such IDs without conflict.
So allocateIds seems perfect for what I am trying to do. I want to use the method to allocate all the auto incremented ids from Mysql so that I can then use the datastore Id generator without worrying about collision.
However I can't find this method anywhere. I am using the cloud datastore java library as a standalone library, without using the app engine.
The Cloud Datastore API does not expose a method for reserving a user-specified ID. The AllocateIds method picks IDs for you.
One possible approach would be to assign the MySQL-generated IDs to the name (string) field in your keys. Cloud Datastore never auto-assigns the name field. The downside is that your application code would be responsible for generating future values.

Best way to remove tokens from database

I'm developing a token based api gateway. Its basically provide a token for authentic clients. So I'm not sure how to remove expired tokens. For every request I checked whether the token is valid or not.
Option 1 is
Mark status of token as expired in database table row.
and create a scheduler to run in midnight to delete expired tokens.
Option 2 is
Delete the token from the row when its expired.
In here No need to run a scheduler.
Normally this API Gateway will handle around 1000 requests per second and and this will increase day by day.
So I'm not sure which option I should use.
The technology I have used is.
Spring mvc,Spring data jpa and Postgre DB. Will deploy on tomcat server.
Neither of the two options is particularly good as both will modify a table row and therefore generate I/O. At 1,000 q/s you need a better solution. On 2ndQuadrant is a blog post on authenticating users through connection pooling in the context of row-level security. The blog post has some issues IMHO and non-relevant material as well so I'll try to redo it here in the right way (or read my comment on the blog post over there).
In Java - as in most other programming languages and/or frameworks - connection pooling is the preferred way to connect to a database server for performance reasons. There is an implicit contract that the application requests a Connection instance from the pool, uses it and then returns the instance to the pool for some other thread. Holding on to a Connection is not an option as it breaks the pooling logic. So proceed as follows:
Connection pool object
Create a connection pool object with database cluster credentials. That role should be GRANTed all necessary privileges on tables and other objects.
Authentication
In the application a user authenticates doing myapp_login(username, password) or something similar using a Connection from the pool. In the database the credentials are checked against a table users or whatever it is called in your setup. If a match is found then create a random token and insert that in a table:
CREATE UNLOGGED TABLE sessions (
token text DEFAULT uuid_generate_v4()::text,
login_time timestamp DEFAULT CURRENT_TIME,
user_name integer,
...
);
Add as many fields as you want. I use a uuid here (cast to text, read on) but you could also md5() some data or use some pg_crypto routine.
This table has to be fast so it is UNLOGGED. That means it is not crash-safe and will be truncated after some server error but that is not a problem: all database sessions will have been invalidated anyway. Also, do not put any constraints like NOT NULL on the table because the only access to this table is through the functions that you as a developer design, no ordinary user ever touches this table, and every constraint involves more CPU cycles.
The myapp_login() function looks somewhat like this:
CREATE FUNCTION myapp_login(uname text, password text) RETURNS text AS $$
DECLARE
t text;
BEGIN
PERFORM * FROM app_users WHERE username = uname AND pwd = password;
IF FOUND THEN
INSERT INTO sessions(user_name) VALUES (uname) RETURNING token INTO t;
EXECUTE format('SET SESSION "my_app.session_user" TO %s', t);
RETURN t;
END IF;
SET SESSION "my_app.session_user" = '';
RETURN NULL;
END;
$$ LANGUAGE plpgsql STRICT SECURITY DEFINER;
REVOKE EXECUTE ON FUNCTION myapp_login(text, text) FROM PUBLIC;
GRANT EXECUTE ON FUNCTION myapp_login(text, text) TO myapp_role;
As you can see, the token is also set in an environment variable with SET SESSION (which needs a literal text value, hence the uuid::text cast and the EXECUTE command) and then returned to the caller. That session token should be stored somewhere in your application code on the Java side.
The function does a lookup on the app_users table and an INSERT on the sessions table. The first is cheap, the second is expensive.
Resume the same session for further queries
If your app user needs further database access after the first queries, then get a Connection instance from the connection pool again, but don't call myapp_ login() but myapp_resume(token) instead. This latter function looks up the token in the sessions table (cheap) and, if found, sets the session variable to this new token. You can also check that the login_time value is recent or set it with the CURRENT_TIME to keep the session "alive" (expensive) or do any other necessary business.
The trick is to keep resuming the session as lean as possible because this is likely to be happening multiple time during a session (from the application perspective).
Close the session
When your app user is done, do myapp_logout(token) which deletes the row from the sessions table that corresponds to the token.
Sessions that are not properly closed are not deleted from the sessions table, but I would not worry too much about that.You could schedule a job that runs once a week to delete all rows that are older than 6 hours or so. That would also allow you to figure out where the error comes from, for instance.
A final word on the token. A uuid is just a random number, but you could also make a hash of the application user name with some random data and use that, for instance, in RLS or some other row-based access mechanism; the blog post I link to above has good info on that. In an application I have developed myself I link the row from the users table to what the user is allowed to see. In either case you should really weigh the pro's and con's: a hash that can be used in RLS sounds nice, but it requires the hash to be re-calculated (which tends to be expensive) and compared to the session hash on every query, a repeated lookup against a users table is also an overhead. Setting another session variable that can be checked at query time with current_setting() might be a good alternative.
I think the easiest way would be like this. When you generate token in your database, you can store time of generation. So that when client sends a request to your database, you can check if it's expired and delete it in request time.

Is it a bad practice to expose DB internal IDs in URLs?

Is it a bad practice to expose DB internal IDs in URLs?
For example, suppose I have a users table with some IDs (primary key) for each row. Would exposing the URL myapp.com/accountInfo.html?userId=5, where 5 is an actual primary key, be considered a "bad thing" and why?
Also assume that we properly defend against SQL injections.
I am mostly interested in answers related to the Java web technology stack (hence the java tag), but general answers will also be very helpful.
Thanks.
That bases on the way you parse the URL. If you allow blind SQL injections that is bad. You have to only to validate the id from the user input.
Stackexchange also puts the id of the row into the URL as you can see in your address bar. The trick is to parse the part and get did of all possible SQL. The simples way is to check that the id is a number.
It isn't a bad thing to pass through in the URL, as it doesn't mean much to the end user - its only bad if you rely on that value in the running of your application. For example, you don't want the user to notice that userId=5 and change it to userID=10 to display the account of another person.
It would be much safer to store this information in a session on the server. For example, when the user logs in, their userID value is stored in the session on the server, and you use this value whenever you query the database. If you do it this way, there usually wouldn't be any need to pass through the userID in the URL, however it wouldn't hurt because it isn't used by your DB-querying code.
To use the database ID in URLs is good, because this ID should never change in an objects (db rows) life. Thus the URL is durable - the most important aspect of an URL. See also Cool URIs don't change.
Yes it is a bad thing. You are exposing implementation detail. How bad? That depends. It forces you to do unneeded checks of the user input. If other applications start depending on it, you are no longer free to change the database scheme.
PKs are meant for the system.
To the user, it may represent a different meaning:
For e.g.
Let's consider following links. Using primary-key,it displays an item under products productA, productB,productC;
(A)http://blahblahsite.com/browse/productA/111 (pkey)
(B)http://blahblahsite.com/browse/productB/112 (pkey)
(C)http://blahblahsite.com/browse/productC/113 (pkey)
User on link B may feel there are 112 items under ProductB, which is misleading.
Also it will cause problem while merging tables since PK will be auto-incremented.

Categories

Resources