Auth
A service for all your authn and authz needs.
Background
A list of articles we have found useful to make this service:
Server
The server is composed of the below operations.
OAuth 2.0
This service supports the following endpoints:
Generate Password
The service allows you to generate a secure password. The system uses:
The user can specify a length. The default is 32 and above.
We take recommendations from NIST Password Guidelines.
Generate Key
The service allows you to generate a secure public and private keys.
RSA
The service will create a key pair using 4096 bits. This is the default or when you pass the kind rsa
.
Ed25519
The service will generate a key pair of Ed25519. This is achieved by passing the ed25519
kind.
Generate Access Token
Access tokens are generated with RSA key pair as created by the key service. The user can specify a length. The default is 32 and above.
Once this is generated it is configured as follows:
key:
rsa:
public: base64-public-key
private: base64-private-key
[key.rsa]
public = "base64-public-key"
private = "base64-private-key"
These keys should be stored and retrieved from an application configuration system.
The service needs administrators to create these access tokens. This is configured as follows:
server:
v1:
admins:
- id: su-1234
hash: password-hash
[[server.v1.admins]]
id = "su-1234"
hash = "password-hash"
Each admin has an id and a hash. The password and hash are generated by the password service. The user then sends id:password
as Basic Authentication. This will give you an encrypted access token. This token is a password that is encrypted with the public key. So you could always generate your own token if needed.
The password and token should be stored and retrieved from an application configuration system. The hash is safe to just leave as is, not need to securely store it.
Issuer
This is used to add the issuer to service tokens. This is configured as follows:
server:
v1:
issuer: https://auth.falkowski.io
[server.v1]
issuer = "https://auth.falkowski.io"
Get Public Key
The service allows you to get the public key by kind. The supported kinds are the same as generating a key.
Generate Service Tokens
Service tokens are generated using Ed25519 key pair. Once this is generated it is configured as follows:
key:
ed25519:
public: base64-public-key
private: base64-private-key or env:VARIABLE
[key.ed25519]
public = "base64-public-key"
private = "base64-private-key or env:VARIABLE"
The system generates service tokens from the access tokens. This is configured as follows:
server:
v1:
services:
- id: e1602e185cba2a90d8bbcfc3f3c5530c
name: service-name
hash: password-hash
duration: 24h
[[server.v1.services]]
id = "e1602e185cba2a90d8bbcfc3f3c5530c"
name = "service-name"
hash = "password-hash"
duration = "24h"
Each service has an id, hash and duration. The access token is generated by the access token service. The user then sends the access token as Bearer Authentication. This will give you an encrypted service token with subject, audience and issuer that is valid for the duration.
JWT
The system will by default generate JWT tokens, or if we specify kind to be jwt
.
Paseto
The system will generate a paseto token if the kind that is passed in is paseto
.
Validate Service Tokens
The systems allows the validation of service tokens. The token is passed as Bearer Authentication along with a kind, audience and action.
Casbin
Casbin is used to authorize the token. Currently it is configured using ACL, using the following:
casbin:
model: |
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
policy: |
p, subject, audience, action
[casbin]
model = """
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
"""
policy = """
p, subject, audience, action
"""
Policy
Here is an explanation of the different terms:
Subject
: This is the current service that gets the token to send to the service.
Audience
: Is the destination service you will be sending the token to.
Action
: Is the action/method of the service you are trying to authorize against.
Check out How it works?
Client
The client can be used in other projects.
./auth client --help
Start the client.
Usage:
auth client [flags]
Flags:
--generate-service-token string generate a service token
-h, --help help for client
--verify-service-token string verify a service token
Global Flags:
--input string input config location (format kind:location, default env:CONFIG_FILE) (default "env:CONFIG_FILE")
This is configured as follows:
client:
v1:
host: server_host
timeout: 1s
access: token generated by server
[client.v1]
host = "server_host"
timeout = "1s"
access = "token generated by server"
Rotate
There might be a need to rotate all the server configuration. This is why we have the rotate command.
./auth rotate --help
Regenerate an existing configuration.
Usage:
auth rotate [flags]
Flags:
-h, --help help for rotate
--output string output config location (format kind:location, default env:ROTATE_CONFIG_FILE) (default "env:ROTATE_CONFIG_FILE")
Global Flags:
--input string input config location (format kind:location, default env:CONFIG_FILE) (default "env:CONFIG_FILE")
Development
If you would like to contribute, here is how you can get started.
Structure
The project follows the structure in golang-standards/project-layout.
Dependencies
Please make sure that you have the following installed:
Style
This project favours the Uber Go Style Guide
Setup
The get yourself setup, please run the following:
make setup
Binaries
To make sure everything compiles for the app, please run the following:
make build-test
Specs
To run all the specs, please run the following:
make specs
Features
To run all the features, please run the following:
make features
Changes
To see what has changed, please have a look at CHANGELOG.md