create restapi with token authentication - java

I'm trying to create RestApi first time. Looking for assistance after reading text present online.
My requirement is, I want to create an rest api which will be having username and password. Password will be in encrypted format. So when this api client will request to a web server, that password will be decrypted first on server side and then if the user name and password authenticates then it will send back a temporary token with expiry date. Then again that token will be used in rest api to request data from the web server in xml format.
How can we achieve this ?
And I also want to understand if we encrypt a password in client server then how its get decrypts on web server side. Is the same instance travels from client to web server side while making request ?
Second, The data which I'm trying to consume from web server are the email ids of users which registers on website. My question, If user is getting registered on website then website must be storing those email ids somewhere like in database right ? And my restApi will be accessing the code on web-server side which is responsible to get email ids from database in xml format. Is my understanding correct ?

First, don't concern yourself directly with encrypting details client-side and decrypting them server-side. If you are using TLS/HTTPS (which you should be) then all is well, everything is already encrypted.
The token generation is slightly more difficult but still easy enough. A commonly used and simple to implement method is to use JWT tokens. The general idea is that you create a JSON object like the following:
{ "userID": "FC5A47CC", "expiry": "12/10/2017" }
And then run it through an HMAC using a key only your server knows. You append the result of the HMAC to the JSON object using base64 encoding and then send this to your client after they have logged in.
Using this method, authentication is very fast, as your web server won't need to make any requests to your database server to determine if the token is valid. You can read more about JWT here. I've answered a similar question in more detail here.
As your question asks, these userIDs will obviously need to be stored in your database.

Seems like you want client app to consume resources on behalf of user. I propose OAuth 2.0, which provides mechanism, which you have described to access protected resources without storing passwords. Client app requests a username and password from the user (for example by using a login form) and then send that credentials to the server. Upon receipt and validation server returns token to the client. Client stores token locally and discards username and password. All subsequent request are authorized by token, which can be accomplished using a custom HTTP header, for example X-Auth-Token. Server can optionally provide a refresh token along with the access token, which is used by client to obtain new access token, once current expires. HTTPS/SSL technology is required by OAuth 2.0, so data over wire will be encrypted.
There are 4 roles defined by OAuth 2.0 :
1) Authorization Server — does identity verification and grants token to the client app.
2) Resource Server — Server which hosts actual protected user resource.
3) Resource Owner — User willing to provide access to his protected resource.
4) Client — application that gets access to a user’s resources.
You can use Spring Security OAuth framework to implement this requirement.

Related

Spring Authorization Server. What's the difference between RegistredClient and UserDetails?

On their Getting started guide, reference, Spring Authorization Server have a piece of code where they declare two beans - UserDetailsService and RegistredClientRepository. I wanted to play around retrieving some tokens from the server. I tried using postman. Within authorization tab I entered the values from the guide:
it answered with:
So then I tried inputting client credentials from RegistredClientRepository entry:
And it worked.
So my question is: what is the purpose of UserDetails and RegistredClient being both available in this case?
And another little bit off-topic question: if I create my own authorization server for client credentials flow between my servers, how does every server know that token belongs to legitimate server and not to some attacker who can just register with needed clientId if there's an opportunity? How can resource server actually verify that token owner is the server it trusts?
Generally in oauth2, a "client" is an application which users might use to interface with some service - for example something like an App people can install on their phones or a web application.
Most oauth2 implementations have "scopes" (basically defined sets of access rights). Clients (client applications) are registered with some metadata (name, author, ...), a set of scopes they might use and some details to improve security - like "where is that application hosted" (in form of "which redirect URIs are valid"), client ID and client secret.
Depending on the oauth2 flow chosen, your App needs to prove being that app by some means - e.g. by having a valid combination of client ID and redirect URI or by doing HTTP basic auth with their client ID as username and client secret as password when exchanging a "code" for a "token".
All this was about clients - now about users: they are what you would expect, the users of a service - like you and me are users on Stackoverflow.com
And another little bit off-topic question: if I create my own
authorization server for client credentials flow between my servers,
how does every server know that token belongs to legitimate server and
not to some attacker who can just register with needed clientId if
there's an opportunity? How can resource server actually verify that
token owner is the server it trusts?
for this you could either use a form of signed tokens (look at e.g. JWT) or store the currently valid tokens per user in a database reachable by all your servers - both have pro's and con's, tokens in a database are easier to revoke, while signed tokens don't require you to store any state in a database (which can be expensive in big distributed systems)
Update - OP actually wants to do server-to-server authentication, see comments below
Server-to-server authentication can often work very well without any extra authentication server, in cases where your parties a less dynamic - like when you always have "those three servers" and they don't come and go very often.
In such cases, using a simple token is probably better and easier than using an oauth2 stack. Each server could just have a list of randomly generated strings in its config file, let's call this "the set of valid tokens" and also knows which token to send when communicating with a specific other server. When a request comes in, the server checks if the given token is in its set of valid tokens - done.

Keycloak JWT Validation using Java Spring Security + KC Adapter

I have gone through multiple blog posts and StackOverflow questions before writing my own. I have multiple queries and none of the posts answer them.
I am using Keycloak Spring Security Adapter to secure my legacy Spring application. I referred to the keycloak documentation here and was able to have OAuth flow running for me. I am using Client Id and Secret as Client Authenticator.
For eg: Access to localhost:8080/about.htm will redirect me to keycloak login screen and after successful authentication, I will be able to view my page. I am also using the below code to read the user details from the token,
KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) auth.getPrincipal();
IDToken idToken = kp.getKeycloakSecurityContext().getIdToken();
user.setUsername(idToken.getPreferredUsername());
Now when I test this application using postman and modify the generated access token, obviously the server gives an error. Ref : How to test application using postman.
However, this is the flow :
Client sends a request to the resource server, resource server checks for a token - if it exists, the client does the validation. If it doesn’t exist or is invalid, it redirects to the authorization server (KC).
My question is,
Who is validating this token? How does postman flow throw an error
if I fiddle with the token?
Do I really need to write a JwtTokenValidator in my application for
each request? Won't that be overkill?
If I use Client Authenticator as Signed Jwt with client secret, will this validation still be required? I am not using it as it introduces latency.
Please assist.
Answer to #1:
When you use any Keycloak adapters in your application (in your case the Spring adapter for Keycloak), that's the one who does the validation and redirects to the login if necessary. As part of the validation, it checks the signature of the token issued by Keycloak. So when you fiddle with the token, the signature doesn't match, hence it throws an error.
Answer to #2
No, you shouldn't need to implement a JwtTokenValidator. The adapter does it for you and a request should reach your endpoint/URL only if it has a valid token. You may only need to do that if you have a special requirements about validating the token (e.g. checking specific claim in the token against some service). Otherwise, you can safely use the claims in the token you received from the KeycloakSecurityContext. You can even setup authorization based on your URL patterns and Keycloak will enforce them too and allow the request to pass if user has necessary roles (like this example).
Answer to #3:
That option only changes the method used to authenticate your app to the Keycloak and has nothing to do with the user's token validation inside your app. In your current setup, when your app wants to communicate with Keycloak (e.g. to exchange auth code with auth token), it authenticate itself to Keycloak with a client-id/client-secret pair (otherwise Keycloak would not know it's your app and will reject the request).
If you choose the "Signed Jwt with Client Secret" option, your client can not just use a client-secret to authenticate to Keycloak. It should support the RFC7523 specification. So it's quite complex in compare with a simple clien-secret approach. In an environment in which you trust your clients (e.g. they're all known apps developed inside the company and you're not going to support public clients to join your Keycloak and use its services) it's quite common and safe to use client-secret approach.

How to properly access an SQL DB from Android securely

I'm in in process of looking to create an Android app; security is obviously the most important thing to keep in mind.
What is the best-practice for authenticating a user and handling business logic (scenario below).
For example, the current design would facilitate the permissions based on the user's login. When a user logs in and successfully authenticates, their Username and Password are stored in session variables. When the user attempts to request a resource that requires a certain permission to view, as part of the process for accessing the resource their Username and Password is sent up to the intermediary Web Service, if this authenticates with the correct permission-set the resource is then accessible.
Is this a reasonable way of operating an Android application or is there a better solution to handling this?
Thanks.
Presumably you're referring to building some sort of web API such as REST API that the Android App would send requests to and the API performs the database actions.
I wouldn't send the username/password combo for every request that tends to be bad practice. You send the user/password combo once to authenticate and the authentication returns some sort of token and this token is then sent in every request and is validated on the API side to ensure it is a valid session token. You could either roll this yourself or use some sort of Single Sign On (SSO) solution such as Google Sign on for example or OAUTH is a common authentication mechanism. Maybe https://oauth.net/ will help.

AngularJS - Java EE REST security

I am using AngularJS along with REST API on Java EE 7 backend.
The project is deployed on a Wildfly application server and I have some questions regrading securities:
To Encrypt/decrypt data I am using CryptoJS to encrypt and decrypt on server side ( Java ) but apparently we have to send the passphrase in clear, the cipher and salt are only encrypted.
My question is why the passphrase is clear text ? it should be secret and then encrypted as well no ?
For the REST API, what is the standard to use for Java EE 7, HTTP security header (basic-auth) ? Json Access token ? and how it really works, where to store user session/token, on a cookie ? I just want to know how to do it with Angular.
Maybe I can use the classic JAAS with form-based authentication and then having request.login() on server side to be authenticated then my EJB will be all protected by #Role.
What is the way to protect pages in AngularJS ? For the moment I am using the web.xml and putting the URL patterns, maybe there is a better way ?
I already found lot of examples like this:
AngularJs and Jboss and JAAS ( omnisecurity )
how to integrate angularjs and java jaas based authentication?
Some users mentions this:
* index.html page should contain token inside html to avoid CSRF
* token shouldn't be stored in a cookie storage
* Each request should be signed with header param
* Server should validate every request by passed header
* If cookie usage is a must you should validate referer in order to prevent CSRF
But there is not concrete example on how to implement this, especially the CSRF.
To Encrypt/decrypt data I am using CryptoJS to encrypt and decrypt on
server side ( Java ) but apparently we have to send the passphrase in
clear, the cipher and salt are only encrypted. My question is why the
passphrase is clear text ? it should be secret and then encrypted as
well no ?
As soon as you are sending a key (passphrase?) in clear - the encryption is useless.
To achieve reasonable client-server security, use the HTTPS. Simple, effective and much more secure. Generally it is a bad idea to encrypt on the web application side, as the user or a 'man-in-the-middle' can retrieve or modify the key and data.
The different case is end-to-end security, when the client encrypts, posts encrypted data and they are stored/processed as they are, with the encryption key available only to the user. If it's not the case and the service needs the data for further operations, the HTTPS is the way to go.
For the REST API, what is the standard to use for Java EE 7, HTTP security header (basic-auth) ? Json Access token ? and how it really
works, where to store user session/token, on a cookie ? I just want to
know how to do it with Angular.
Effectively you listed you options. This is your decision. Every option has its pros and cons. Basically - if you're talking about (REST) services, it shouldn't matter what technology is used.
For the REST services called directly from the browser I'd omit the basic authentication (otherwise user would get the pop-up authentication window)
You can use the JWT token (signed by the application secret, just add some expiration date), but then you cannot 'logout' the user, just wait until the token expires. The advantage is, that the token is 'self-sufficient' and you need not to worry about the session management. The client sends the JWT token in the Authorization HTTP header, you just decode it, validate and then you can assume the identity from the token.
Another option is a session token (cookie or sent as an Authorization header), where you need to manage the sessions (store the tokens, clear the token out on logout, ...). Using the app server session cookies makes your services unusable by other applications (still a question - do you want/need the services to be reusable by third parties), but you achieve built-in authorization (JAAS , Roles, ...).
Maybe I can use the classic JAAS with form-based authentication and
then having request.login() on server side to be authenticated then my
EJB will be all protected by #Role.
Indeed, this is a way how you authenticate and authorize the user and issue a token (jwt, cookie, other...).
What is the way to protect pages in AngularJS ? For the moment I am
using the web.xml and putting the URL patterns, maybe there is a
better way ?
The default web authorization should be ok.
Still - keep it simple. According to my experiences the static resources (web pages, images, scripts, css) should be static and it shouldn't really matter if they are publicly available. The important is the execution (operations, data, ...) are exposed as the services and that's the point where you do proper authentication and authorization.
Have fun

android sign in button and remote web login in PHP ZF2

I googled and I only found documents on how to create a sign in button on your android application, or how to create a sign in button on your web application.
My scenario is that the android application retrieves information from my website using get/post http requests and getting json data.
I have a working android sign in button on my android application.
the question is that when i want to retrieve information from my website using get/post request, what information should I send in order for the website to know which user is retrieving that information and that the user is logged in ?
I know that I can't just send the google user id because that's not secured and easly hacked. I'm guessing I need to send some kind of access token and on the web site to parse that access token in order to know which user it is. but what exactly do I need to do?
My client side is PHP with ZendFramework 2 and ZfcUser with scn-social-auth for google login.
any information regarding the issue would be greatly appreciated.
thanks
In my previous staff project, i've implemented our Api modules for Zend Framework (it was version 1 but it is the same for version 2).
Basically, i've implemented the OAuth protocol 1.0 ( rfc at https://www.rfc-editor.org/rfc/rfc5849 ), that is a really strong way to improve the connection security between a generic client ( Android, iOS, Mac OSX, Windows Phone ,... ) and web service.
Shortly it consits into enforce the https protocol ( i hope you are working in httpS ) signing all the client get/post requests with the base OAuth parameters ( such as oauth_version,oauth_token,... all explained in rfc) in order to avoid MITM and proxy to alter the request. Using this method i've make a specific table into which store Request and Access Tokens.
So:
Client has consumer key and consumer secret
Server has same consumer key and consumer secret
OAuth will use that keypair to authenticate the connection
Client obtain "Request Token" from server
Client perform common username and password login through OAuth workflow to the server
Client obtain Access Token ( if login with success ) that will be stored on the token db table, and wil be used to check if that user on that device is logged in and so authorized to use the service (so you'll probably need a device guid also )
You can find good guidelines and good github projects on how implement your own OAuth protocol ( see also service like Dropbox or Twitter developer sections, about how they use OAuth for their service ). Consider that you can obviously customize your OAuth protocol once implemented, with additional controls and tokens ( i've used AES-256 encryption and RSA 2048 bit for some custom tokens, and also to encrypt username and password for the login with a received key combination in the previous step expected by OAuth workflow ).
In the end, you can connect the clients to your web service with your custom tokens so, once authenticated, you make you web service to interact with google service and return information to client always through your website
Hope it helps
If the user login server is the same with the one that you want to retrieve information,you can use the sessionId as the token.
1.After authentication,server store userId in the session
2.Server use session_id() to get sessionId ,return it to android client
3.add ?PHPSESSID=sessionId param to the android client http request.
4.Server get userId from the session
session_start() creates a session or resumes the current one based on a session identifier passed via a GET or POST request, or passed via a cookie.
You can add GET parameter PHPSESSID to any requested url.
$manager = \Zend\Session\Container::getDefaultManager();
//$manager = new \Zend\Session\SessionManager();
$PHPSESSID = $manager->getId();

Categories

Resources