passing parameter in http header with REST service - java

Right now i'm using java to build rest service, and trying to use spring security to securing my service.
I have a few parameter that server needs to process the service (ex: application ID, username, password, consumer ID) . For username and password, I put in on http header "authorization", encoded with base64. Is there a way to put another parameters above (ex. AppID, consID) into http header?
Some sample of code would help, thanks.

You can put whatever you want in a whatever header you like. You can create custom headers. So you can have a App-Id header where you pass the appId. Alternatively you can pass those as parameters in the URL. That way you'll get rid of the option that some (stupid) proxy trims your headers.
Btw, I would suggest not to send the password, unless you are using https. Generally, I can recommend two similar scenarios:
use OAuth - let the user grant access to the API client via the OAuth dance. The client ends up with a token which it uses on each request.
use a custom, simplified token scheme - login once (with username and password, over https), and send a short-lived token in response. Each subsequent request can be made over an unsecured connection by providing the token, and (optionally) some HMAC of the request parameters, using a consumer secret as a key, so that you can verify the client is legit.

Related

Implementing a token style security when doing GET requests

I'm implementing a temporary and very simple token-style authentication mechanism for an application.
The idea is very simple. Whenever a user logs in to the application, a token is returned to the client, which stores it in the sessionStorage data structure of the browser.
Now, whenever I do a request through AJAX I can send the token with the request and the server can verify if this token is associated with an authentication or username. If it is, it parses the request normally, if not, a error page or the initial page is returned or displayed.
I'm not sure if this is the way that token-style authentication and authorization is implemented in real or serious applications, but I've now no idea how to send the token when doing GET requests by just clicking on the link of a view.
My only idea would be to intercept the get requests so that I can fill them with the token, but this all seems to be quite odd, and I've already a lot of links and views.
Search for Json Web Tokens and for implementations on java. This is exactly what you need.
If you want to send to the user some sensitive data inside the jwt, use Json Web Encryption.
You can send that token on each request header or as a request parameter
You can set a cookie, ensure to set it httponly (ans secure if you are on an https site) and read the cookie on every request that reach the server.
You can use JWT token (see https://jwt.io/introduction/). JWT is basically a JSON data structure. Usually, the token is passed along in the authorization http header.

How to use token based authorization on REST?

So after reading lots about BasicAuth, OAuth, JWT... etc. i came up with this question.
I have a client where some ppl can log in (Authentication is done). When ppl want to do an api call they use the clients GUI and the client is sending some requests to the a webservice endpoint.
host/resources/{id}
//id=path, res=post
public Response updateResourceById(String id, Resource res) {
....
So a typical update call could be
POST host/resources/1234 -d={ some json for a resource }
Now i don't want every user to have all rights for every reosurce, so i would
need to add some info about the user who is doing a request.
For this i was thinking to use some JSON Token with some payload (or any user info at all). But i was wondering how to send this token correctly in a RESTful API.
My first idea would be to change the code to something like this:
//id=path, token=post
public Response updateResourceById(String id, Token token) {
...
The endpoint would not change only the POST data.
Would this be correct or are there other approaches?
Edit: Also possible would be sending the Token via HTTP Header.
Sending credentials in HTTP
In HTTP, the credentials should be sent in the standard HTTP Authorization header.
Have a look at the RFC 7235, the current reference for authentication in HTTP 1.1:
4.2. Authorization
The Authorization header field allows a user agent to authenticate
itself with an origin server -- usually, but not necessarily, after
receiving a 401 (Unauthorized) response. Its value consists of
credentials containing the authentication information of the user
agent for the realm of the resource being requested.
Authorization = credentials
[...]
Please note that the name of this HTTP header is unfortunate because it carries authentication data instead of authorization. Anyways, this is the standard header for sending credentials.
In a token based authentication, the tokens are credentials. In this approach, hard credentials such as username and password are exchanged for a token that is sent in each request to identify a user.
It never hurts to say that you should use HTTPS when sending sensitive data, such as credentials, over the wire. HTTPS will protect your application against the man-in-the-middle attack.
Reading the authentication token in JAX-RS
You can read the Authorization header in a JAX-RS application as following and then check if the token is valid:
#GET
public Response myMethod(#HeaderParam("Authorization") String token) {
...
}
However, a better approach would be using a ContainerRequestFilter, keeping your endpoints leans and focused on the business logic. For more information on token based authentication and on how to use a ContainerRequestFilter, have a look at this question.

Does it needs to pass username:password combination in any request with basic auth?

I confused with basic http authorization. It is needed to send every request to server with Authorization header or just first one and after that browser rember auth tokens like session id?
You have to send the Authorization header on each request. But for example Chrome remembers the auth tokens and sends it automatically on each request.
Using basic authentication, every request needs to have an Authorization HTTP header in the format:
Authorization: Basic <base64(username:password)>
where the username and password are concatenated using a colon (':') and the resulting string is base64 encoded.
If the Authorization header is not part of the request, or the credentials inside are not valid, the server should respond with an HTTP 401 Unauthorized response and include a HTTP header like:
WWW-Authenticate: Basic realm="myRealm"
Basic authentication is an implicit authentication scheme, so after the user enters valid credential, the browser will send them along with each page request.
For AJAX requests you'll need to attach this header from code. However, you really should not use basic authentication to protect an API, for a number of reasons:
You'd force the client to hold those credentials in code, where they can easily be stolen.
You must use HTTPS with basic authentication as base64 encoding gives no protection of the credentials at all.
Username/password combinations are usually valid much longer than an access token, thereby increasing the risk if they get stolen.
Password validation should be a slow process to mitigate brute force attacks, where token validation is just verifying a digital signature.
Having to send the username/password over the wire every time increases the attack surface for someone trying to break the encryption.
Better alternatives to protect web APIs are token based authentication schemes like OAuth2 or HMAC based authentication schemes like Hawk or AWS
Ya that's correct , so for first time when user logs in , his credentials are verified against some data , if correct , a auth token is generated.
Auth token is pretty much a self contained entity (which stores some data signed with a key)
this token gets stores at client side(usually along with a refresh token)
for all subsequent requests , this token is kept in Authorization header(Bearer+token)
When server receives this token , it decrypts it with the key , which it used earlier to sign that token. And uses that stored data
If that auth token is expired , refresh token comes into play.
some links to begin with
On a high level, how does OAuth 2 work?
and jwt.io to get the feel of tokens

Securing REST Web Service using token (Java)

This question is in some way related to the below linked question. However, I need a little more clarity on some aspects and some additional information. Refer:
REST Web Service authentication token implementation
Background:
I need to implement security for a REST Web Service using token
The webservice is intended for use with Java client. Hence, form
authentication and popups for credentials are not useful.
I'm new to REST security and encryption
This is what I have understood till now:
For first request:
User establishes https connection (or container ensures https using
301)
User POSTs username and password to login service
If credentials are valid we:
Generate a random temporary token
Store the random token on server mapping it to actual username
Encrypt the token using a symmetric key only known to server
Hash the encrypted token
Send the encrypted token and the hash to the client
For subsequent requests:
Client sends this encrypted token and hash combination (using
username field of basic?)
We make sure the encrypted token is not tampered using the hash and
then decrypt it
We check the decrypted token in the session-tracking-table for a
not-expired entry and get the actual username (expiry to be managed
by code?)
If the username is found, based on allowed roles, allowed operations
are configured
More details:
Since client is a java client, the first request can be a POST
containing the credentials. However, this looks like it may expose
the credentials before the https gets established. Hence should
there be a dummy GET to a secured resource so that https is
established first?
Assuming above is required, the second request is a LoginAction POST
with credentials. This request is handled manually (not using
container's authorisation). Is this right?
The above LoginAction returns the user the combination of encrypted
token + hash
User sets it to the header that is used by BASIC authentication
mechanism (field username)
We implement a JAASRealm to decrypt and validate the token, and find
the roles allowed
The rest of authorisation process is taken care of by the container
with the WebResourceCollection defined in the web.xml
Is this the correct approach?
Why not simplify it to the following?
For first request:
User establishes HTTPS connection to server (service does not listen on any
other ports) and POSTs credentials to login service.
Server replies with HSTS header to ensure all further communication
is HTTPS.
If credentials are valid we:
Generate a random temporary token which is securely generated using a CSPRNG. Make this long enough to be secure (128 bit).
Store the random token on server mapping it to actual username.
Send the random token to the client
For subsequent requests:
Client sends token in a custom HTTP header over HTTPS.
Token is located in the DB and mapped to the username. If found access is configured based on allowed roles and allowed operations.
If not found user is considered unauthenticated and will have to authenticate with the login service again to get a new token.
On the server side the token will be stored with an expiry date. On each access to the service this date will be updated to create a sliding expiration. There will be a job that will run every few minutes to delete expired tokens and the query that checks the token for a valid session will only check those that have not deemed to have expired (to prevent permanent sessions if the scheduled job fails for any reason).
There is no need to hash and encrypt the tokens within the database - it adds no real value apart from a touch of security through obscurity. You could just hash though. This would prevent an attacker that managed to get at the session data table from hijacking existing user sessions.
The approach looks ok. Not very secure.
Let me highlight some of the attacks possible with the request.
Man-In-the-middle attack in a POST request, the user can tamper with the request and server does not have any way to ensure the data is not tampered.
Replay attack: In this, the attacker does not tamper with the request. The attacker taps the request and sends it to the server multiple times in a short duration, though it is a valid request, the server processes the request multiple times, which is not needed
Please read about Nonce.
In the first step, the user sends his credentials i.e username and password to the login service and if you have a web based application that also uses the same password it might be dangerous. If in case password in compromised, API and web everything is exposed, please use a different PIN for API access. Also, ensure decrypted token as specified by you, expires after a certain time.
Ensure the service (application server) tomcat. jboss never returns a server page in case of internal error, this gives the attacker extra information of the server where the app is deployed.
-- MODIFIED BASED ON SECOND POST --
Yes your correct if your using mutual SSL, but in case its a one way access you don't have the client certificates. It would be good if you just double ensured everything in the request, just like signed (signature) SOAP, one of the strong data transfer mechanism. But replay attack is a possibility with HTTPS, just handle that. Rest use tokens encryption is good. And why not ask the client to decrypt the token with the password and return the output of the decryption by this you can validate the output, if it is present in your database ? This approach the user does not send the password over the wire even if it is HTTPS ?

Supplying an authentication token via HTTPComponents library

I am using the HTTPComponents library for this implementation.
My RESTful implementation comprises of supplying a username/password, to generate a token. This token, in turn is supplied as a header to the ensuing API calls as:
authorization = <40 char token>
However, a method.addRequestHeader("authorization","<40 char token>"); isn't authenticating the service call.
Do I need to specify the token differently?
I think this is acceptable method to pass token in httpheader.
but try to send token after encoding on network for more secure transmission.

Categories