Securing REST Web Service using token (Java)

11,243

Why not simplify it to the following?

For first request:

  1. User establishes HTTPS connection to server (service does not listen on any other ports) and POSTs credentials to login service.
  2. Server replies with HSTS header to ensure all further communication is HTTPS.
  3. 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:

  1. Client sends token in a custom HTTP header over HTTPS.
  2. Token is located in the DB and mapped to the username. If found access is configured based on allowed roles and allowed operations.
  3. 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.

Share:
11,243
Teddy
Author by

Teddy

Develops Enterprise software and Cloud products using Java EE & Web technologies. In the business of making high-quality and reliable systems.

Updated on June 04, 2022

Comments

  • Teddy
    Teddy almost 2 years

    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:

    1. User establishes https connection (or container ensures https using 301)
    2. User POSTs username and password to login service
    3. 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:

    1. Client sends this encrypted token and hash combination (using username field of basic?)
    2. We make sure the encrypted token is not tampered using the hash and then decrypt it
    3. 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?)
    4. If the username is found, based on allowed roles, allowed operations are configured

    More details:

    1. 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?
    2. 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?
    3. The above LoginAction returns the user the combination of encrypted token + hash
    4. User sets it to the header that is used by BASIC authentication mechanism (field username)
    5. We implement a JAASRealm to decrypt and validate the token, and find the roles allowed
    6. 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?