README

Steranko 🔐

GoDoc Go Report Card Build Status Codecov

Website Authentication/Authorization for Go

This project is a work-in-progress, and should NOT be used by ANYONE, for ANY PURPOSE, under ANY CIRCUMSTANCES. It is GUARANTEED to blow up your computer, send your cat into an infinite loop, and combine your hot and cold laundry into a single cycle.

Steranko is an embeddable library that manages user authentication, and authorization. You can configure it at run time (or compile time) to meet your specific project needs.

To use Steranko, you have to implement two tiny interfaces in your code, then wire Steranko's handlers into your HTTP server.

s := steranko.New(userService, steranko.Conig{
  Tokens: "cookie:auth",
  PasswordSchema: `{"type":"string", "minLength":20}`
})

s.Register(echo)

Project Goals

  • Create a configurable, open source authentication/authorization system in Go.

  • Hashed passwords using bcrypt

  • Automatically upgrade password encryption cost on signin.

  • Lock out user accounts after N failed attempts.

  • Maintain security with JWT tokens

  • Password strength checking (via JSON-Schema extensions)

  • Password vulnerability via HaveIBeenPwned API.

Possible future additions
  • Identify malicious users with a (relatively) invisible CAPTCHA system
    • Track javascript events during signup (keyup, keydown, mousemove, click)
    • Track timing of events. They must not be too fast, or too consistent.
    • Something to prevent requests from being forwarded to an actual human.
    • Math problems?
    • Geolocation.

Pull Requests Welcome

This library is a work in progress, and will benefit from your experience reports, use cases, and contributions. If you have an idea for making Steranko better, send in a pull request. We're all in this together! 🔐

Expand ▾ Collapse ▴

Documentation

Index

Constants

View Source
const CodeForbidden = 403

CodeForbidden is the HTTP status code of an unaccepted authentication.

View Source
const CodeUnauthorized = 401

CodeUnauthorized is the HTTP status code for an authentication failure error.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	Token          string        `json:"token"`          // Where to store authentication tokens.  Valid values are HEADER (default value) or COOKIE
	PasswordSchema schema.Schema `json:"passwordSchema"` // JSON-encoded schema for password validation rules.
}

type RequestPasswordResetResponse

type RequestPasswordResetResponse struct {
}

type RequestPasswordResetTransaction

type RequestPasswordResetTransaction struct {
	Username string `json:"username"` // public username of the person requesting the reset.
}

type SigninResponse

type SigninResponse struct {
	Username     string
	JWT          string
	ErrorMessage string
	Error        error
}

SigninResponse includes all the information returned by Steranko after a signin request.

type SigninTransaction

type SigninTransaction struct {
	Username      string `json:"username"`      // public username for this person
	Password      string `json:"password"`      // private (hashed?) password for this person
	TwoFactorCode string `json:"twoFactorCode"` // [Optional] 2FA code to send to the 2FA plugin
}

SigninTransaction includes all of the information that MUST be posted to Sterenko in order to sign in to the system.

type Steranko

type Steranko struct {
	UserService    UserService           // Service that provides CRUD operations on Users
	Config         Config                // Configuration options for this library
	PasswordHasher plugin.PasswordHasher // PasswordHasher uses a one-way encryption to obscure stored passwords.
	PasswordRules  []plugin.PasswordRule // PasswordRules provide rules for enforcing password complexity
	// contains filtered or unexported fields
}

Steranko contains all required configuration information for this library.

func New

func New(userService UserService, config Config) *Steranko

New returns a fully initialized Steranko instance, with HandlerFuncs that support all of your user authentication and authorization needs.

func (*Steranko) Authenticate

func (s *Steranko) Authenticate(username string, password string) (User, error)

Authenticate verifies a username/password combination.

func (*Steranko) PasswordSchema

func (s *Steranko) PasswordSchema() *schema.Schema

PasswordSchema returns the schema.Schema for validating passwords

func (*Steranko) PostPasswordToken

func (s *Steranko) PostPasswordToken(ctx echo.Context) error

PostPasswordToken implements the http.HandlerFunc signature, and should be wired in to your REST API to allow users to tell the server that they forgot their password. This should initiate some way for the system to send them a one time token to create a new password.

func (*Steranko) PostPasswordUpdate

func (s *Steranko) PostPasswordUpdate(ctx echo.Context) error

PostPasswordUpdate implements the http.HandlerFunc signature, and should be wired in to your REST API to allow users to update their passwords.

func (*Steranko) RequireSignin

func (s *Steranko) RequireSignin()

func (*Steranko) Signin

func (s *Steranko) Signin(txn SigninTransaction) SigninResponse

PostSignin implements the http.HandlerFunc signature, and should be wired in to your REST API to allow users to sign in to their accounts.

func (*Steranko) TrySigning

func (s *Steranko) TrySigning()

func (*Steranko) ValidatePassword

func (s *Steranko) ValidatePassword(password string) error

ValidatePassword checks a password against the requirements in the Config structure.

type UpdatePasswordResponse

type UpdatePasswordResponse struct {
}

type UpdatePasswordTransaction

type UpdatePasswordTransaction struct {
	Username    string `json:"username"`
	OldPassword string `json:"oldPassword"`
	NewPassword string `json:"newPassword"`
}

type User

type User interface {
	GetUsername() string // Returns the username of the User
	GetPassword() string // Returns the password of the User

	SetUsername(username string)    // Sets the username of the User
	SetPassword(ciphertext string)  // Sets the password of the User
	Claims() map[string]interface{} // Returns all claims (permissions) that this user has.
}

User interface wraps all of the functions that Steranko needs to authorize a user of the system. This is done so that Steranko can be retrofitted on to your existing data objects. Just implement this interface, and a CRUD service, and you're all set.

type UserService

type UserService interface {

	// New creates a newly initialized User that is ready to use
	New() User

	// Load retrieves a single User from the database
	Load(username string) (User, error)

	// Save inserts/updates a single User in the database
	Save(user User, comment string) error

	// Delete removes a single User from the database
	Delete(user User, comment string) error

	RequestPasswordReset(user User) error

	// Close cleans up any connections opened by the service.
	Close()
}

UserService wraps all of the functions that must be provided to Steranko by your application. This API matches the presto.Service API very closely, so it should be possible to wrap an existing presto service to serve Steranko, too.