auth

package
v0.0.0-...-efa6b18 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 2, 2024 License: GPL-3.0 Imports: 7 Imported by: 0

README

Authentication

Authentication in this project works in three steps:

  1. first you login and retrieve a refresh token
  2. send your refresh token and retrieve a short-lived access token
  3. send your access token with every api request to access protected recourses

See the example for the most basic authentication flow. Note that the script requests a new refresh-token every time, which should be avoided.

Login

Make a request to /auth/login with your user credentials (username/user Id & password) as json inside the Authorization http header field:

Authorization: {"userId":"<userId>","password":"<password>"}

The order of the json fields does not matter. Note the use of " for valid json.

Usage

If your credentials are valid, you will get a refresh token as a response. Store it somewhere save and use it to request new access tokens.

Fields

Password and either Username or userId are required.

Password

Your password must only contain letters and numbers.

Username

Your username must only contain letters and numbers.

User Id

Your userId.

Refresh Token

A json object containing a selector, token and expiry date used to request access tokens

{ "selector": "<string>", "token": "<string>", "expiryDate": "<int>" }
Obtaining

See login.

Usage

Used to request an access token.

Fields

All fields are required.

selector

The base64 encoded URL-save representation of a random byte[9] array used to retrieved the associated token-hash from the database.

token

The base64 encoded URL-save representation of a byte[33] array used to compare against a hash stored in the database.

expiryDate

An integer representing the UNIX timestamp at which the associated refresh token becomes invalid.

Currently hardcoded to 10 days inside /database/crypto_helpers.go: const refreshTokenLifetime = "+10 day".

Access Token

A JWT (JSON Web Token, learn more) consisting of three base64 encoded URL-save parts separated by dots ..

Decoded & formatted:

{
  "alg": "HS256",
  "typ": "JWT"
}
.
{
  "userId": "<int>",
  "isAdmin": <bool>,
  "isUserCreator": <bool>,
  "expiryDate": <int>
}
.
<signature>
Obtaining

Make a request to /auth with a refresh token inside the Authorization http header:

Authorization: Refresh {"selector":"<string>","token":"<string>","expiryDate":<int>}

Returns:

<base64 encoded header>.<base64 encoded payload>.<base64 encoded signature>
Usage

When included in the Authorization http header, it gives you access based on your user role.

Authorization: Bearer <base64 encoded header>.<base64 encoded payload>.<base64 encoded signature>
Fields

All fields are required.

Header
alg

The algorithm used to create the signature. Currently only HS256 is supported.

type

The IANA Media Type (learn more) of the payload. This field is always set to "jwt".

Payload
userId

The userId associated with the access token.

isAdmin

A boolean indicating if the user has admin rights.

isUserCreator

A boolean indicating if the user has user creation rights.

expiryDate

An integer representing the UNIX timestamp at which the associated refresh token becomes invalid.

Currently hardcoded to 10 minutes inside database/crypto_helpers.go: const accessTokenLifetime = time.Minute * 10.

Signature

A SHA256 hash of the encoded header and payload. The value of database.secret from the config file is used as a key (salt).

Why

We use access tokens with a lifespan of 10 min and an in-memory db to blacklist revoked tokens. So if for e.g. a user changes it's password, we would add the userId and the time of the change to the blacklist, invalidating all tokens of that user that have been issued before.

After a server restart, all tokens will become invalid as well, since we can not be sure which ones were revoked (this could be mitigated in the future by making the blacklist persist during restarts).

If a token has expired (either by a server restart or after 10 min), a new token is requested with a refresh token that is stored in a database.

Pros:
  • less DB lookups in general
Cons:
  • increased load on database after server restart since all active clients need a new access token.

Example

#!/bin/env bash
USERNAME="admin"
PASSWORD="temporaryPassword"

# login (you can replace `userName` with `userId` since the username might change)
REFRESH_TOKEN=$(curl -ksH "Authorization: Login {\"userName\":\"$USERNAME\",\"password\":\"$PASSWORD\"}" https://localhost:4241/auth/login)

# request access token (every 10 minutes or after server restart)
ACCESS_TOKEN=$(curl -ksH "Authorization: Refresh $REFRESH_TOKEN" https://localhost:4241/auth)

# a request to a fictional protected resource
QUERY_RESULT=$(curl -ksH "Authorization: Bearer $ACCESS_TOKEN" https://localhost:4241/protected)

# "convert" the header & access token to a json string to use in client applications (e.g. GraphiQL)
echo -e "Use this as header for e.g. GraphiQL:\n{\"Authorization\":\"Bearer $ACCESS_TOKEN\"}"

Documentation

Overview

YetAnotherToDoList Copyright © 2023 gilex-dev gilex-dev@proton.me

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ForContext

func ForContext(ctx context.Context) *database.AccessToken

func IssueAccessTokenHandler

func IssueAccessTokenHandler(w http.ResponseWriter, r *http.Request)

func IssueRefreshTokenHandler

func IssueRefreshTokenHandler(w http.ResponseWriter, r *http.Request)

func Middleware

func Middleware() func(http.Handler) http.Handler

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL