The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
There is two types of clients:
- User clients: they provide an API to manage a single user session in a client application. In the future, they will also provide UI views to ease the integration into applications.
- Middlewares: they integrate with server frameworks (Django, Express, etc.) to verify token signatures, and inject the decoded token in the request.
As far as possible, clients must follow the idioms and conventions of the target platform/language.
User clients are typically stateful since they need to store the user token and the refresh token. Clients must be thread-safe, such that a client instantiated in one thread, can be safely re-used in another thread.
User clients must implement the following public API:
emailAvailable(email: str) -> boolean
register(email: str, password: str, **fields) -> (boolean, Optional[Error])
login(email: str, password: str) -> (Optional[Dict], Optional[Error])
resetPassword(email: str) -> boolean
userOne(**fields) -> (Optional[Dict], Optional[Error])
userByIds(ids: List[str]) -> (List[Dict], Optional[Error])
userMany(sort: enum[sorts], skip: integer, limit: integer, **filters) -> (List[Dict], Optional[Error])
userCount(**filters) -> integer
userPagination(page: int, perPage: int, sort: enum[sorts], **filters) -> (Optional[Dict] , Optional[Error])
In the login
and refreshToken
functions, the user is decoded from the token returned by the server.
In the user...
functions, all public fields are requested.**
update(**fields) -> (Optional[Dict], Optional[Error])
delete(password: str) -> (Optional[Error])
changePassword(oldPassword: str, newPassord: str) -> Optional[Error]
sendVerificationEmail() -> boolean
The following functions may be implemented in the public or private API of the client. They are typically not used directly by the user.
publicKey() -> str
refreshToken() -> (Optional[Dict], Optional[Error])
User clients must provide a way to make authenticated requests to any other URLs not part of the Krypton Authentication API.
It is done by setting in the Authorization
HTTP header the following value Bearer {token}
, {token}
being the user token.
This can be done in two ways.
User clients must provide a function returning the user token and its expiryDate. The user token must not be expired nor close to be expired (less than 2 minuts).
getToken() -> (token, expiryDate)
Note: the refresh token is not exposed as it is internal to Krypton Authentication.
User clients should provide an API to make authenticated HTTP requests including automatically the user token in the Authorization
header. It should also allow to customize requests: HTTP method, target, version, headers (other than the Authorization header) and body.
TBD
If permitted by the language, errors must be raised as typed exceptions, such that the client can be used as follow:
client = KryptonClient()
try:
client.register(...)
except EmailAlreadyExistsError:
print('Email already exists...')
Error messages and their internationalization must be provided by the client.
The user token (JWT) can be invalidated at any time, either because it expired, or because it was deleted from the server.
- For every authenticated request the client must check whether or not an error was returned from the server.
- If a
UnauthorizedError
is returned, it must try to obtain a new token using therefreshToken
mutation. - If a new token is obtained, then it must perform the request again, and return the result to the user.
- Otherwise the user is considered as logged-out, and a
UnauthorizedError
exception is raised.
Middlewares must integrate with server frameworks (Django, Express, etc.) in their standard way. It should verify token signatures, and inject the decoded token into the request so that other middlewares can access the user data.
Middlewares must receive in argument the Krypton Authentication URL which can be a relative one (if Krypton Authentication is running on the same server) or an absolute one. It will be able to fetch automatically the public key from Krypton Authentication in order to verify token signatures.
It must not decode the token if it is expired or if its signature is invalid.
If the decryption fails, it should not raise an exception but simply pass the request to the next middleware.