is

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jan 19, 2021 License: Apache-2.0 Imports: 9 Imported by: 0

README

Identity Server

A package that essentially provides an easy-to-use gin middleware to secure http server routes.

go get github.com/a-novel/identity-server

Configuration

Identity Server works with Gin and Couchbase.

For an easy setup of Couchbase, you can use the Divan Docker package.

Identity Server needs some configuration to connect and access data on your Couchbase cluster.

{
  "cluster": {
    "url": "couchbase://172.1.3.19",
    "username": "super-secret-username",
    "password": "super-secret-password"
  },
  "users": {
    "db_name": "my-users",
    "email_path": "u.`confidential`.`email`",
    "password_hashed_path": "u.`confidential`.`password_hashed`"
  }
}
Cluster (Configuration)
Key Required Default Description
url - localhost Url for the cluster
username true - Username for cluster administrator
password true - Password for cluster administrator
Users (Configuration)
Key Required Default Description
db_name true - Bucket name where user data is stored
username - u.`email` JSON path for user email within user document
password - u.`password_hashed` JSON path for user password within user document

For paths, u represents the document root.

Init

Once your configuration file is ready, you can run the init function in your main go file:

package myPackage

import (
	"github.com/a-novel/identity-server"
	"log"
)

func init() {
	if err := is.Init("/path/to/configuration/file.json"); err != nil {
		log.Fatal(err.Error())
	}
}

Use

Now you have run the Init function, you can add the Identity Server middleware to any of your gin handlers. Below are a few examples:

package myPackage

import (
	"github.com/a-novel/errors"
	"github.com/a-novel/identity-server"
	"github.com/gin-gonic/gin"
	"reflect"
)

type UserDocument struct {
	// Anything you want in here. This mirrors the JSON representation of your user, with credentials located at
	// email_path and password_hashed_path.
}

// main() is called after init()
func main() {
	r := gin.Default()
	
	opts := is.AuthOptions{
		Parser: func(c *gin.Context) (*is.UnencryptedAuthentication, *errors.Error) {
			// Return an Unencrypted Authentication object from request context.
		},
		InterruptOnFailure: true,
		InterruptOnAuthFailure: true,
    }

	r.GET(
		"/path/to/secure/resource",
		is.Middlewares.Authenticate(reflect.TypeOf(UserDocument{}), opts),
		// Your other middlewares here.
	)
}
Options
Parser

Parser is a function that will take a gin context and return an authentication object. Context may involve request body or any other source for user data.

InterruptOnFailure and InterruptOnAuthFailure

Both flags will determine the middleware behavior if any error occurs. Both will abort the request with an error status when set to true, if anything occurs.

InterruptOnAuthFailure will abort if authentication fails, while InterruptOnFailure will catch any other error.

If one or both of those flags are set to false, errors will be registered in the gin context, with the possibility to check them afterwards.

CheckAuthStatus
func MyMiddleware(c *gin.Context) {
    err, authErr, unErr := is.MiddlewaresUtils.CheckAuthStatus(c)
}

CheckAuthStatus will retrieve any error that occurred with the Authenticate middleware. It will return nil values if no error occurred, or if the middleware wasn't called in the first place.

err indicates any error that occurred under the scope of InterruptOnFailure, while authErr indicates that no valid credentials where given, but the request proceeded successfully. unErr should not happen and indicates an error during the retrieval process.

Retrieve user document

On later middleware, and after validating that authentication was successful, you can retrieve the full user document from gin context.

The type of user document if a pointer to the one you passed as first argument of the middleware wrapper.

func MyMiddleware(c *gin.Context) {
	rawDoc, ok := c.Get(is.GinAuthDataKey)
	if !ok {
	    // Shouldn't happen, handle error here.	
    }
    
    doc := rawDoc.(*UserDocument)
}

License

2021, A-Novel Apache 2.0 License.

Documentation

Index

Constants

View Source
const (
	ErrCannotFindValidConfiguration = isauth.ErrCannotFindValidConfiguration
	ErrCannotRunQuery               = isauth.ErrCannotRunQuery
	ErrWrongPassword                = isauth.ErrWrongPassword
	ErrUserNotFound                 = isauth.ErrUserNotFound
	ErrCannotReadUserDocument       = isauth.ErrCannotReadUserDocument
	ErrCannotReadUserCredentials    = isauth.ErrCannotReadUserCredentials
	ErrEmailDouble                  = isauth.ErrEmailDouble
	ErrUnexpectedError              = isauth.ErrUnexpectedError
	ErrMissingEmail                 = isauth.ErrMissingEmail
	ErrMissingPassword              = isauth.ErrMissingPassword
	ErrEmailTooLong                 = isauth.ErrEmailTooLong
	ErrPasswordTooLong              = isauth.ErrPasswordTooLong
	ErrWrongEmailFormat             = isauth.ErrWrongEmailFormat
	ErrCannotHashPassword           = isauth.ErrCannotHashPassword
)
View Source
const (
	ErrMissingClusterUsername = isconf.ErrMissingClusterUsername
	ErrMissingClusterPassword = isconf.ErrMissingClusterPassword
	ErrMissingUsersDBName     = isconf.ErrMissingUsersDBName
	ErrCannotAccessCluster    = isconf.ErrCannotAccessCluster
)
View Source
const (
	ErrUnexpectedKey = isginerrors.ErrUnexpectedKey
	ErrMissingParser = isginerrors.ErrMissingParser
	ErrNoCredentials = isginerrors.ErrNoCredentials
)
View Source
const (
	GinParseErrorKey = isginutils.GinParseError
	GinAuthErrorKey  = isginutils.GinAuthError
	GinAuthDataKey   = isginutils.GinAuthData
)

Variables

View Source
var Middlewares = struct {
	Authenticate func(userDocument reflect.Type, opts isginstructs.AuthOptions) func(c *gin.Context)
}{
	Authenticate: isgin.Auth,
}
View Source
var MiddlewaresUtils = struct {
	CheckAuthStatus func(c *gin.Context) (*errors.Error, *errors.Error, *errors.Error)
}{
	CheckAuthStatus: isginutils.CheckAuthStatus,
}

Functions

func Init

func Init(configPath string) *errors.Error

Types

type AuthOptions

type AuthOptions = isginstructs.AuthOptions

type Authentication

type Authentication = isauth.Authentication

type EncryptConfig

type EncryptConfig = isauth.EncryptConfig

type UnencryptedAuthentication

type UnencryptedAuthentication = isauth.UnencryptedAuthentication

Directories

Path Synopsis
middlewares
gin
tests

Jump to

Keyboard shortcuts

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