The authentication system is designed by myself while working on a project called Spherium. The project itself is not published though, I put it there as a state-of-the-art experience log, showing that kind of thing is extremely doable in Phoenix, and Elixir.
This is the artifact of the project I’m implementing right now, with documentation-driven development. I’m planning to open-source the implementation in the future, do not hesitate to ask me about implementation side. You know ma mail.
Why authentication is required?
Spherium uses usage related information in order to supply precise data to the clients. The data of the users and its availability matters. Therefore, in order to perform some actions, Spherium needs to authenticate the user due to philosophical and technical reasons, it provides a layer of access control.
The web service utilizes unified authentication mechanism and it requires two steps of authentication to be successfully completed to authorize to the application.
Artifacts of authentication
Several authentication artifacts are used during the process.
This artifact is a property of user, may contain sensitive data. It uniquely identifies its owner.
This artifact is a property of user. It should be used carefully since it will probably contain sensitive data of the user. It is persisted in back-end storage layer as hashed with either bcrypt or pbkdf2 etc.
This artifact is generated on the server dynamically and constitutes the second factor of authentication. It is an unsigned integer value between
1.000.000 inclusive from start, excluding the end.
This artifact is stateless and generated by multi-factor-authentication (MFA) device (i.e. Google Authenticator). After initial configuration of the device, the workflow does not consist any kind of communication between sides, the code generated is timestamp salted.
This artifact provides an ability to grant access on the server. It has long expiration of time and it could be stored in a device. A valid passphrase will be adequate to grant access to a user.
JSON Web Token
This is a standardized artifact, according to RFC 7519. It contains user data, which provides stateless authentication. In many circumstances, the payload of this artifact could be read by client application, but not mutated. In case of mutation, it will invalidate itself.
HTTP over TLS
TLS between two endpoints will be necessary in order to make communication encrypted. API will not respond to unencrypted connections in order to prevent attacks (i.e. man-in-the-middle, MITM).
Usernames and passwords are user-declared credentials. These properties should not be persisted by client application. Without using further prevention of authentication with scheme preference, this will make the account vulnerable to such attacks.
Passphrase (Access Token)
From IETF RFC 6749 10.10 Credentials-Guessing Attacks:
The probability of an attacker guessing generated tokens (and other credentials not intended for handling by end-users) MUST be less than or equal to 2^(-128) and SHOULD be less than or equal to 2^(-160).
According to OAuth 2.0 security guidelines, generated tokens should be in a range of a predefined value. A passkey consists of 88 8-bit characters, resulting in 8^88 permutations. Therefore, in order to reach insecure range, there could be 2^104 total passkeys.
Steps of authentication
Authentication stage is conducted by two steps:
Concrete authentication: User credentials are provided by the client, it reflects a polymorphic workflow depending on user’s preference of authentication.
Stealth authentication: Passphrase is provided by the client silently, in order to renew JSON Web Token.
Concrete authentication workflow
Since there are different authentication schemes, the number of steps may differ between users. However, those authentication schemes work as different interfaces to passphrase step, each authentication scheme will make challenger to arrive to fetch the passphrase.
- Supplying user credentials to the service.
Every authentication scheme will be instantiated by supplying user credentials to the server. The endpoint to submit user credentials forms a unified interface to all available authentication schemes. The response will consist information about trailed authentication scheme, hence the front-end application will be available to inform user about authentication state.
There are three different flow graphs of workflow, representing each authentication scheme:
- Insecure (bypass)
Returning a passphrase of the user.
- No further authentication step will be needed.
- Weak security layer.
- Two-factor authentication over SMS
Waiting a passphrase request with one-time-code.
- The reason underneath requesting an OTC is making one of the credentials to access to the web service dynamic. Usernames, emails and passwords are all static type of data. However, OTC is generated on the server dynamically per request, making itself dynamic.
- Generally, OTC’s have short expiration times (or time-to-live, TTL). This web service is configured to examine OTC tokens with an expiration time of 180 seconds.
- Falls through step 2.
- Two-factor authentication over external authenticator
Waiting a passphrase request with time-based-code.
- External authenticators use time-based-code, which is generated by synchronized timestamp and be able to be used offline.
- TBC’s also have short expiration TTL’s, configured by external authenticator authority, likely to be less than a minute.
- Falls through step 2.
- Requesting a passphrase (which includes a passkey) with dynamic artifact.
- Passphrases are 86-digit access tokens which provides a unique access authority to the server. This abstraction layer is needed since usernames and passwords may contain sensitive data of a user, these artifacts could not be persisted in client-side. However, passphrases could be securely persisted, it is generated in the server randomly and has no relation with user’s data.
- Supplying a correct dynamic artifact to the server, the two-factor authentication becomes completed. Henceforth, the user should not be informed about the ongoing process, since no additional information will be requested.
- Passphrases have longer expiration times compared to other authentication artifacts. This web service is configured to examine passphrases with an expiration time of 5 months. One important thing about these artifacts is they could be manually invalidated by owner user or certain authorities, making them useless. Since this artifact is the smallest matter of access to the server resources, in case of misuse, it may lead to catastrophic circumstances.
- Passphrases are generated uniquely, they are not pooled: One invalidated/expelled could not refer an access to such user.
Stealth authentication workflow
There are three ways to authenticate to the API, who are interfaced via a unified endpoint. Even though concrete authentication workflow will be different between users, depending upon preferences of them, stealth authentication will be same. The word stealth refers to silence of the action, the user interface ought to not show state of this workflow. Generally, this will be most used step of the total workflow.
- Requesting a JSON Web Token (JWT) with a passphrase.
- JWTs contain a payload, which carries the user information, providing a stateless authentication opportunity to the server. It could be decoded also in the client application, but not manipulated.
- As it is said, being provided by the response upon creation of the token, the default value of expiration of a JWT is 30 minutes. It is not a good idea to rely on that specific amount of time, however, one should understand the expiration of the token will be the amount provided.
Invalidation of successful authentication
Passphrase is an artifact of a successful authentication session. Normally, they have a valid duration of 5 months, however they could also be invalidated manually, simulating a pseudo-sign out action. Invalidation is a destructive operation and cannot be undone, whereas such invalidated passkey could not be assigned to another user.
Resetting user password
Password is a static credential of the user, hence it could be forgotten by its owner. The API provides a special way to reset the credential in case of lose. Password reset is a special type of passphrase invalidation, it invalidates all existing passphrases immediately. User will not be able to use another authenticated (signed in) device after that operation.
Tracking malicious probing
Some 3rd party authorities might probe authentication mechanism in order to perform masquerade attack. Rate limiting is one of the good ways to prevent from these type of attacks since probing is often performed by brute-force denial-of-service attempts. The web service does not provide a layer of rate limiting due to technical concerns, however this could be easily achieved by running the application behind a all-purpose performant web server (i.e. Nginx, Apache). The master server could apply a rate limiting, though, with its supervision on request quota.
While rate limiting performs prevention of incognito and malicious access, it does not store any further information. The web service provides authentication attempt listing. An authentication attempt could be gathered with API routes.