-
Notifications
You must be signed in to change notification settings - Fork 653
Security Steps
The project has a private.pem
and public.pem
file to allow the project to work out of the box with security. Please don't use these keys for your production system. The project has support for generating new private and public key files.
The project also has a bare minimum user system for creating users and generating JSON Web Tokens (JWTs). This document will walk you through the entire process of applying authentication and authorization to the project. All the support for security will be found in the Sales-Admin
application.
Security is applied to routes in the Sales-Api
application. This is done through the use of middleware.
app.Handle(http.MethodPost, "/v1/users", u.create, mid.Authenticate(authenticator), mid.HasRole(auth.RoleAdmin))
app.Handle(http.MethodGet, "/v1/users/:id", u.retrieve, mid.Authenticate(authenticator))
In the example above, routes require a JWT that is valid and the /v1/users
route requires the Admin
role. In the case of the /v1/users/:id
route, extra logic is applied in the business layer.
func (u *user) retrieve(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
claims, ok := ctx.Value(auth.Key).(auth.Claims)
if !ok {
return errors.New("claims missing from context")
}
params := web.Params(r)
usr, err := data.Retrieve.User.One(ctx, claims, u.db, params["id"])
}
func (retUser) One(ctx context.Context, claims auth.Claims, db *sqlx.DB, userID string) (*User, error) {
. . .
// If you are not an admin and looking to retrieve someone other than yourself.
if !claims.HasRole(auth.RoleAdmin) && claims.Subject != userID {
return nil, ErrForbidden
}
. . .
}
This logic above restricts users to only retrieving information about themselves unless they are an admin. In this case, the claims are passed to the business layer for more refined security processing.
Generating a set of public and private keys is the first thing you will want to do unless you plan to use the keys provided by the project.
To generate your own set of private and public key files, use the keygen
command.
$ cd $HOME/code/service/cmd/sales-admin
$ go run main.go genkey
OUTPUT:
private and public key files generated
The result of running this command should be two new files in the current directory. Keep the private.pem
file secure and out of reach to anyone who should not have it.
For production systems, you DO NOT want to store the private key with the project._
You must have the database started and the migration run before you can execute any user management functions. For now, use the project's key files until you learn more.
To start the database and run the migration, run these commands.
$ cd $HOME/code/service/
$ make up-local
OUTPUT:
docker run -it -d -p 5432:5432 postgres:11.1-alpine
c4b58ffa0944b74b002e883f85b54ce72287f73bff7f7d98933793acf5d5e76f
$ make migrate
OUTPUT:
migrations complete
Adding a user requires four piece of information: username, email, password, role. The current roles that will be used with the application are: ADMIN, MUTATE, QUERY.
$ cd cmd/sales-admin
$ go run main.go --db-disable-tls=1 useradd [email protected] gopher
OUTPUT:
user id: c2c8b7df-0e99-4f63-a78d-fb24dfc59256
Generating a JWT requires a user to already exist in the database. This requires three pieces of information: user-email, private-key-file, algorithm. The algorithm choices are: RS256 or HA256. I recommend using RS256.
$ go run main.go --db-disable-tls=1 gentoken c2c8b7df-0e99-4f63-a78d-fb24dfc59256 ../../private.pem RS256
OUTPUT:
-----BEGIN TOKEN-----
eyJhbGciOiJSUzI1NiIsImtpZCI6IjU0YmIyMTY1LTcxZTEtNDFhNi1hZjNlLTdkYTRhMGUxZTJjMSIsInR5cC
I6IkpXVCJ9.eyJyb2xlcyI6WyJBRE1JTiIsIlVTRVIiXSwiZXhwIjoxNjIzNDI2NDg2LCJpYXQiOjE1OTE4OTA
0ODYsImlzcyI6InNlcnZpY2UgcHJvamVjdCIsInN1YiI6ImMyYzhiN2RmLTBlOTktNGY2My1hNzhkLWZiMjRkZ
mM1OTI1NiJ9.SvB_mPQ20IlA61qnYNybZT6EGxBiftGGJel8G0IaXVEaLqm5lhOw-HwMGlx06W7KsukZhX5AKU
OnhUHbtri6SaFjb8mlvoRbcxL8mDdgmu3m9saS0gtnewW37SjqmcHG88121v3iDzxCoWmeJ_jSvLdKtDD6Lq8R
jYeiHfFddtR0SSyzzUwslJxUWu-h8fkXDxJ4NXoIBVD7hi8F_SpxtUJiIYjK70jP2PETSOPYIsuMbofWegh6t7
16XigfXc8kn4-SYAs9bbBZ-Y6IVjMws4K1704hJf0FsZarlY5Q85u1MsGRzIJpWL-cyAD24IRPXPo8oF2any-e
jtr8w2fYlg
-----BEGIN TOKEN-----
To check if the JWT is valid, go to the JWT Website and copy/paste the token in the debugger.
Contact Bill Kennedy at [email protected] if you are having issues getting the project running.