auth

package
v0.33.0 Latest Latest
Warning

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

Go to latest
Published: Nov 28, 2025 License: Apache-2.0 Imports: 9 Imported by: 0

README

Auth - Authentication and Authorization service

Auth service provides authentication features as an API for managing authentication keys as well as administering groups of entities - things and users.

Authentication

User service is using Auth service gRPC API to obtain login token or password reset token. Authentication key consists of the following fields:

  • ID - key ID
  • Type - one of the three types described below
  • IssuerID - an ID of the Mainflux User who issued the key
  • Subject - user email
  • IssuedAt - the timestamp when the key is issued
  • ExpiresAt - the timestamp after which the key is invalid

There are three types of authentication keys:

  • User key - keys issued to the user upon login request
  • API key - keys issued upon the user request
  • Recovery key - password recovery key

Authentication keys are represented and distributed by the corresponding JWT.

User keys are issued when user logs in. Each user request (other than registration and login) contains user key that is used to authenticate the user.

API keys are similar to the User keys. The main difference is that API keys have configurable expiration time. If no time is set, the key will never expire. For that reason, API keys are the only key type that can be revoked. This also means that, despite being used as a JWT, it requires a query to the database to validate the API key. The user with API key can perform all the same actions as the user with login key (can act on behalf of the user for Thing, Profile, or user profile management), except issuing new API keys.

Recovery key is the password recovery key. It's short-lived token used for password recovery process.

For in-depth explanation of the aforementioned scenarios, as well as thorough understanding of Mainflux, please check out the official documentation.

The following actions are supported:

  • create (all key types)
  • verify (all key types)
  • obtain (API keys only)
  • revoke (API keys only)

Groups

User and Things service are using Auth gRPC API to get the list of ids that are part of a group. Groups can be organized as tree structure. Group consists of the following fields:

  • ID - ULID id uniquely representing group
  • Name - name of the group, name of the group is unique at the same level of tree hierarchy for a given tree.
  • ParentID - id of the parent group
  • OwnerID - id of the user that created a group
  • Description - free form text, up to 1024 characters
  • Metadata - Arbitrary, object-encoded group's data
  • Path - tree path consisting of group ids
  • CreatedAt - timestamp at which the group is created
  • UpdatedAt - timestamp at which the group is updated

Configuration

The service is configured using the environment variables presented in the following table. Note that any unset variables will be replaced with their default values.

Variable Description Default
MF_AUTH_LOG_LEVEL Service level (debug, info, warn, error) error
MF_AUTH_DB_HOST Database host address localhost
MF_AUTH_DB_PORT Database host port 5432
MF_AUTH_DB_USER Database user mainflux
MF_AUTH_DB_PASSWORD Database password mainflux
MF_AUTH_DB Name of the database used by the service auth
MF_AUTH_DB_SSL_MODE Database connection SSL mode (disable, require, verify-ca, verify-full) disable
MF_AUTH_DB_SSL_CERT Path to the PEM encoded certificate file
MF_AUTH_DB_SSL_KEY Path to the PEM encoded key file
MF_AUTH_DB_SSL_ROOT_CERT Path to the PEM encoded root certificate file
MF_AUTH_HTTP_PORT Auth service HTTP port 8180
MF_AUTH_GRPC_PORT Auth service gRPC port 8181
MF_AUTH_SERVER_CERT Path to server certificate in pem format
MF_AUTH_SERVER_KEY Path to server key in pem format
MF_AUTH_SECRET String used for signing tokens auth
MF_AUTH_LOGIN_TOKEN_DURATION The login token expiration period 10h
MF_INVITE_DURATION Duration of validity of created Org invites 168h
MF_JAEGER_URL Jaeger server URL localhost:6831
MF_EMAIL_HOST Mail server host localhost
MF_EMAIL_PORT Mail server port 25
MF_EMAIL_USERNAME Mail server username
MF_EMAIL_PASSWORD Mail server password
MF_EMAIL_FROM_ADDRESS Email "from" address
MF_EMAIL_FROM_NAME Email "from" name
MF_EMAIL_BASE_TEMPLATE Path to base template for e-mails sent from the service base.tmpl

Deployment

The service itself is distributed as Docker container. Check the auth service section in docker-compose to see how service is deployed.

To start the service outside of the container, execute the following shell script:

# download the latest version of the service
go get github.com/MainfluxLabs/mainflux

cd $GOPATH/src/github.com/MainfluxLabs/mainflux

# compile the service
make auth

# copy binary to bin
make install

# set the environment variables and run the service
MF_AUTH_LOG_LEVEL=[Service log level] MF_AUTH_DB_HOST=[Database host address] MF_AUTH_DB_PORT=[Database host port] MF_AUTH_DB_USER=[Database user] MF_AUTH_DB_PASS=[Database password] MF_AUTH_DB=[Name of the database used by the service] MF_AUTH_DB_SSL_MODE=[SSL mode to connect to the database with] MF_AUTH_DB_SSL_CERT=[Path to the PEM encoded certificate file] MF_AUTH_DB_SSL_KEY=[Path to the PEM encoded key file] MF_AUTH_DB_SSL_ROOT_CERT=[Path to the PEM encoded root certificate file] MF_AUTH_HTTP_PORT=[Service HTTP port] MF_AUTH_GRPC_PORT=[Service gRPC port] MF_AUTH_SECRET=[String used for signing tokens] MF_AUTH_SERVER_CERT=[Path to server certificate] MF_AUTH_SERVER_KEY=[Path to server key] MF_JAEGER_URL=[Jaeger server URL] MF_AUTH_LOGIN_TOKEN_DURATION=[The login token expiration period] $GOBIN/mainfluxlabs-auth

If MF_EMAIL_TEMPLATE doesn't point to any file service will function but password reset functionality will not work.

Usage

For more information about service capabilities and its usage, please check out the API documentation.

Documentation

Index

Constants

View Source
const (
	UserTypeInvitee = "invitee"
	UserTypeInviter = "inviter"

	InviteStatePending  = "pending"
	InviteStateExpired  = "expired"
	InviteStateRevoked  = "revoked"
	InviteStateAccepted = "accepted"
	InviteStateDeclined = "declined"
)
View Source
const (
	// LoginKey is temporary User key received on successful login.
	LoginKey uint32 = iota
	// RecoveryKey represents a key for resseting password.
	RecoveryKey
	// APIKey enables the one to act on behalf of the user.
	APIKey
)
View Source
const (
	// RoleRootAdmin is the super admin role.
	RoleRootAdmin = "root"
	// RoleAdmin is the admin role.
	RoleAdmin = "admin"
)
View Source
const (
	Admin   = "admin"
	Owner   = "owner"
	Editor  = "editor"
	Viewer  = "viewer"
	RootSub = "root"
	OrgSub  = "org"
)

Variables

View Source
var (
	// ErrInvalidKeyIssuedAt indicates that the Key is being used before it's issued.
	ErrInvalidKeyIssuedAt = errors.New("invalid issue time")

	// ErrKeyExpired indicates that the Key is expired.
	ErrKeyExpired = errors.New("use of expired key")

	// ErrAPIKeyExpired indicates that the Key is expired
	// and that the key type is API key.
	ErrAPIKeyExpired = errors.New("use of expired API key")
)
View Source
var (
	// ErrCreateOrgMembership indicates failure to create org membership.
	ErrCreateOrgMembership = errors.New("failed to create org membership")

	// ErrRemoveOrgMembership indicates failure to remove org membership.
	ErrRemoveOrgMembership = errors.New("failed to remove org membership")

	// ErrOrgMembershipExists indicates that membership already exists.
	ErrOrgMembershipExists = errors.New("org membership already exists")
)
View Source
var (
	// ErrRetrieveMembershipsByOrg indicates that retrieving memberships by org failed.
	ErrRetrieveMembershipsByOrg = errors.New("failed to retrieve memberships by org")

	// ErrRetrieveOrgsByMembership indicates that retrieving orgs by membership failed.
	ErrRetrieveOrgsByMembership = errors.New("failed to retrieve orgs by membership")
)
View Source
var ErrInvalidInviteResponse = errors.New("invalid invite response action")

ErrInvalidInviteResponse indicates an invalid Invite response action string.

View Source
var (
	// ErrOrgNotEmpty indicates org is not empty, can't be deleted.
	ErrOrgNotEmpty = errors.New("org is not empty")
)

Functions

This section is empty.

Types

type Authn

type Authn interface {
	// Identify validates token token. If token is valid, content
	// is returned. If token is invalid, or invocation failed for some
	// other reason, non-nil error value is returned in response.
	Identify(ctx context.Context, token string) (Identity, error)
}

Authn specifies an API that must be fullfiled by the domain service implementation, and all of its decorators (e.g. logging & metrics). Token is a string value of the actual Key and is used to authenticate an Auth service request.

type Authz

type Authz interface {
	Authorize(ctx context.Context, ar AuthzReq) error
}

Authz represents a authorization service. It exposes functionalities through `auth` to perform authorization.

type AuthzReq

type AuthzReq struct {
	Token   string
	Object  string
	Subject string
	Action  string
}

AuthzReq represents an argument struct for making an authz related function calls.

type Backup

type Backup struct {
	Orgs           []Org
	OrgMemberships []OrgMembership
}

type Emailer added in v0.30.0

type Emailer interface {
	SendOrgInvite(to []string, inv OrgInvite, orgName, invRedirectPath string) error
}

type Identity

type Identity struct {
	ID    string
	Email string
}

Identity contains ID and Email.

type Invites added in v0.30.0

type Invites interface {
	// CreateOrgInvite creates a pending Invite on behalf of the User authenticated by `token`,
	// towards the user identified by `email`, to join the Org identified by `orgID` with an appropriate role.
	CreateOrgInvite(ctx context.Context, token, email, role, orgID, invRedirectPath string) (OrgInvite, error)

	// CreateDormantOrgInvite creates a pending, dormant Org Invite associated with a specfic Platform Invite
	// denoted by `platformInviteID`.
	CreateDormantOrgInvite(ctx context.Context, token, orgID, role, platformInviteID string) (OrgInvite, error)

	// RevokeOrgInvite revokes a specific pending Invite. An existing pending Invite can only be revoked
	// by its original inviter (creator).
	RevokeOrgInvite(ctx context.Context, token, inviteID string) error

	// RespondOrgInvite responds to a specific invite, either accepting it (after which the invitee
	// is assigned as a member of the appropriate Org), or declining it. An Invite can only be responded
	// to by the invitee that it's directed towards.
	RespondOrgInvite(ctx context.Context, token, inviteID string, accept bool) error

	// ActivateOrgInvite activates all dormant Org Invites associated with the specific Platform Invite.
	// The expiration time of the invites is reset. An e-mail notification is sent to the invitee for each
	// activated invite.
	ActivateOrgInvite(ctx context.Context, platformInviteID, userID, invRedirectPath string) error

	// ViewOrgInvite retrieves a single Invite denoted by its ID.  A specific Org Invite can be retrieved
	// by any user with admin privileges within the Org to which the invite belongs,
	// the Invitee towards who it is directed, or the platform Root Admin.
	ViewOrgInvite(ctx context.Context, token, inviteID string) (OrgInvite, error)

	// ListOrgInvitesByUser retrieves a list of invites either directed towards a specific Invitee,
	// or sent out by a specific Inviter, depending on the value of the `userType` argument, which
	// must be either 'invitee' or 'inviter'.
	ListOrgInvitesByUser(ctx context.Context, token, userType, userID string, pm PageMetadataInvites) (OrgInvitesPage, error)

	// ListOrgInvitesByOrg retrieves a list of invites towards any user(s) to join the org identified
	// by its ID
	ListOrgInvitesByOrg(ctx context.Context, token, orgID string, pm PageMetadataInvites) (OrgInvitesPage, error)

	// SendOrgInviteEmail sends an e-mail notifying the invitee of the corresponding Invite.
	SendOrgInviteEmail(ctx context.Context, invite OrgInvite, email, orgName, invRedirectPath string) error
}

type Key

type Key struct {
	ID        string
	Type      uint32
	IssuerID  string
	Subject   string
	IssuedAt  time.Time
	ExpiresAt time.Time
}

Key represents API key.

func (Key) Expired

func (k Key) Expired() bool

Expired verifies if the key is expired.

type KeyRepository

type KeyRepository interface {
	// Save persists the Key. A non-nil error is returned to indicate
	// operation failure
	Save(context.Context, Key) (string, error)

	// Retrieve retrieves Key by its unique identifier.
	Retrieve(context.Context, string, string) (Key, error)

	// Remove removes Key with provided ID.
	Remove(context.Context, string, string) error
}

KeyRepository specifies Key persistence API.

type Keys added in v0.24.0

type Keys interface {
	// Issue issues a new Key, returning its token value alongside.
	Issue(ctx context.Context, token string, key Key) (Key, string, error)

	// Revoke removes the Key with the provided id that is
	// issued by the user identified by the provided key.
	Revoke(ctx context.Context, token, id string) error

	// RetrieveKey retrieves data for the Key identified by the provided
	// ID, that is issued by the user identified by the provided key.
	RetrieveKey(ctx context.Context, token, id string) (Key, error)
}

Keys specifies an API that must be fullfiled by the domain service implementation, and all of its decorators (e.g. logging & metrics).

type Org

type Org struct {
	ID          string
	OwnerID     string
	Name        string
	Description string
	Metadata    OrgMetadata
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

Org represents the org information.

type OrgInvite added in v0.30.0

type OrgInvite struct {
	ID           string
	InviteeID    string
	InviteeEmail string
	InviterID    string
	InviterEmail string
	OrgID        string
	OrgName      string
	InviteeRole  string
	CreatedAt    time.Time
	ExpiresAt    time.Time
	State        string
}

type OrgInvitesPage added in v0.30.0

type OrgInvitesPage struct {
	Invites []OrgInvite
	Total   uint64
}

type OrgInvitesRepository added in v0.30.0

type OrgInvitesRepository interface {
	// SaveOrgInvite saves one or more pending org invites to the repository.
	SaveOrgInvite(ctx context.Context, invites ...OrgInvite) error

	// SaveDormantInviteRelation saves a relation of a dormant Org Invite with a specific Platform Invite.
	SaveDormantInviteRelation(ctx context.Context, orgInviteID, platformInviteID string) error

	// ActivateOrgInvite activates all dormant Org Invites corresponding to the specified Platform Invite by:
	// - Updating the "invitee_id" and "expires_at" columns of all matching Org Invites to the supplied values
	// - Removing the associated rows from the "dormant_org_invites" table
	// Returns slice of activated Org Invites.
	ActivateOrgInvite(ctx context.Context, platformInviteID, userID string, expirationTime time.Time) ([]OrgInvite, error)

	// RetrieveOrgInviteByID retrieves a specific OrgInvite by its ID.
	RetrieveOrgInviteByID(ctx context.Context, inviteID string) (OrgInvite, error)

	// RemoveOrgInvite removes a specific pending OrgInvite.
	RemoveOrgInvite(ctx context.Context, inviteID string) error

	// RetrieveOrgInviteByUser retrieves a list of invites either directed towards a specific Invitee, or sent out by a
	// specific Inviter, depending on the value of the `userType` argument, which must be either 'invitee' or 'inviter'.
	RetrieveOrgInvitesByUser(ctx context.Context, userType, userID string, pm PageMetadataInvites) (OrgInvitesPage, error)

	// RetrieveOrgInvitesByOrg retrieves a list of invites towards any user(s) to join the Org identified
	// by its ID.
	RetrieveOrgInvitesByOrg(ctx context.Context, orgID string, pm PageMetadataInvites) (OrgInvitesPage, error)

	// UpdateOrgInviteState updates the state of a specific Invite denoted by its ID.
	UpdateOrgInviteState(ctx context.Context, inviteID, state string) error
}

type OrgMembership added in v0.29.0

type OrgMembership struct {
	MemberID  string
	OrgID     string
	Role      string
	CreatedAt time.Time
	UpdatedAt time.Time
	Email     string
}

type OrgMemberships added in v0.29.0

type OrgMemberships interface {
	// CreateOrgMemberships adds memberships with member emails into the org identified by orgID.
	CreateOrgMemberships(ctx context.Context, token, orgID string, oms ...OrgMembership) error

	// RemoveOrgMemberships removes memberships with member ids from org identified by orgID.
	RemoveOrgMemberships(ctx context.Context, token string, orgID string, memberIDs ...string) error

	// UpdateOrgMemberships updates membership roles in an org.
	UpdateOrgMemberships(ctx context.Context, token, orgID string, oms ...OrgMembership) error

	// ListOrgMemberships retrieves memberships created for an org identified by orgID.
	ListOrgMemberships(ctx context.Context, token, orgID string, pm apiutil.PageMetadata) (OrgMembershipsPage, error)

	// ViewOrgMembership retrieves membership identified by memberID and orgID.
	ViewOrgMembership(ctx context.Context, token, orgID, memberID string) (OrgMembership, error)

	// BackupOrgMemberships retrieves all org memberships for given org ID.
	BackupOrgMemberships(ctx context.Context, token string, orgID string) (OrgMembershipsBackup, error)

	// RestoreOrgMemberships adds all org memberships for given org ID from a backup.
	RestoreOrgMemberships(ctx context.Context, token string, orgID string, backup OrgMembershipsBackup) error
}

OrgMemberships specify an API that must be fulfilled by the domain service implementation, and all of its decorators (e.g. logging & metrics).

type OrgMembershipsBackup added in v0.29.0

type OrgMembershipsBackup struct {
	OrgMemberships []OrgMembership
}

type OrgMembershipsPage added in v0.29.0

type OrgMembershipsPage struct {
	Total          uint64
	OrgMemberships []OrgMembership
}

OrgMembershipsPage contains page related metadata as well as list of memberships that belong to this page.

type OrgMembershipsRepository added in v0.29.0

type OrgMembershipsRepository interface {
	// Save saves memberships.
	Save(ctx context.Context, oms ...OrgMembership) error

	// Update updates memberships.
	Update(ctx context.Context, oms ...OrgMembership) error

	// Remove removes memberships.
	Remove(ctx context.Context, orgID string, memberIDs ...string) error

	// RetrieveRole retrieves role of membership specified by memberID and orgID.
	RetrieveRole(ctx context.Context, memberID, orgID string) (string, error)

	// RetrieveByOrg retrieves org memberships identified by orgID.
	RetrieveByOrg(ctx context.Context, orgID string, pm apiutil.PageMetadata) (OrgMembershipsPage, error)

	// BackupAll retrieves all memberships.
	BackupAll(ctx context.Context) ([]OrgMembership, error)

	// BackupByOrg retrieves all memberships by org ID.
	BackupByOrg(ctx context.Context, orgID string) ([]OrgMembership, error)
}

type OrgMetadata

type OrgMetadata map[string]interface{}

OrgMetadata defines the Metadata type.

type OrgRepository

type OrgRepository interface {
	// Save orgs
	Save(ctx context.Context, orgs ...Org) error

	// Update an org
	Update(ctx context.Context, org Org) error

	// Remove orgs
	Remove(ctx context.Context, ownerID string, orgIDs ...string) error

	// RetrieveByID retrieves org by its id
	RetrieveByID(ctx context.Context, id string) (Org, error)

	// BackupAll retrieves all orgs.
	BackupAll(ctx context.Context) ([]Org, error)

	// RetrieveAll retrieves all orgs with pagination.
	RetrieveAll(ctx context.Context, pm apiutil.PageMetadata) (OrgsPage, error)

	// RetrieveByMember list of orgs that member belongs to
	RetrieveByMember(ctx context.Context, memberID string, pm apiutil.PageMetadata) (OrgsPage, error)
}

OrgRepository specifies an org persistence API.

type Orgs

type Orgs interface {
	// CreateOrg creates new org.
	CreateOrg(ctx context.Context, token string, org Org) (Org, error)

	// UpdateOrg updates the org identified by the provided ID.
	UpdateOrg(ctx context.Context, token string, org Org) (Org, error)

	// ViewOrg retrieves data about the org identified by ID.
	ViewOrg(ctx context.Context, token, id string) (Org, error)

	// ListOrgs retrieves orgs.
	ListOrgs(ctx context.Context, token string, pm apiutil.PageMetadata) (OrgsPage, error)

	// RemoveOrgs removes the orgs identified with the provided IDs.
	RemoveOrgs(ctx context.Context, token string, ids ...string) error

	// GetOwnerIDByOrgID returns an owner ID for a given org ID.
	GetOwnerIDByOrgID(ctx context.Context, orgID string) (string, error)

	// Backup retrieves all orgs and org memberships. Only accessible by admin.
	Backup(ctx context.Context, token string) (Backup, error)

	// Restore adds orgs and org memberships from a backup. Only accessible by admin.
	Restore(ctx context.Context, token string, backup Backup) error
}

Orgs specifies an API that must be fullfiled by the domain service implementation, and all of its decorators (e.g. logging & metrics).

type OrgsPage

type OrgsPage struct {
	Total uint64
	Orgs  []Org
}

OrgsPage contains page related metadata as well as list of orgs that belong to this page.

type PageMetadataInvites added in v0.30.0

type PageMetadataInvites struct {
	apiutil.PageMetadata
	State string `json:"state,omitempty"`
}

type Roles

type Roles interface {
	// AssignRole assigns a role to a user.
	AssignRole(ctx context.Context, id, role string) error

	// RetrieveRole retrieves a role for a user.
	RetrieveRole(ctx context.Context, id string) (string, error)
}

type RolesRepository

type RolesRepository interface {
	// SaveRole saves the user role.
	SaveRole(ctx context.Context, id, role string) error
	// RetrieveRole retrieves the user role.
	RetrieveRole(ctx context.Context, id string) (string, error)
	// UpdateRole updates the user role.
	UpdateRole(ctx context.Context, id, role string) error
	// RemoveRole removes the user role.
	RemoveRole(ctx context.Context, id string) error
}

type Service

type Service interface {
	Authn
	Authz
	Roles
	Orgs
	OrgMemberships
	Invites
	Keys
}

Service specifies an API that must be fulfilled by the domain service implementation, and all of its decorators (e.g. logging & metrics). Token is a string value of the actual Key and is used to authenticate an Auth service request.

func New

func New(orgs OrgRepository, tc protomfx.ThingsServiceClient, uc protomfx.UsersServiceClient, keys KeyRepository, roles RolesRepository,
	memberships OrgMembershipsRepository, invites OrgInvitesRepository, emailer Emailer, idp uuid.IDProvider, tokenizer Tokenizer, loginDuration time.Duration, inviteDuration time.Duration) Service

New instantiates the auth service implementation.

type Tokenizer

type Tokenizer interface {
	// Issue converts API Key to its string representation.
	Issue(Key) (string, error)

	// Parse extracts API Key data from string token.
	Parse(string) (Key, error)
}

Tokenizer specifies API for encoding and decoding between string and Key.

type User

type User struct {
	ID     string
	Email  string
	Status string
}

Directories

Path Synopsis
api
Package api contains implementation of Auth service HTTP API.
Package api contains implementation of Auth service HTTP API.
grpc
Package grpc contains implementation of Auth service gRPC API.
Package grpc contains implementation of Auth service gRPC API.
Package postgres contains Key repository implementations using PostgreSQL as the underlying database.
Package postgres contains Key repository implementations using PostgreSQL as the underlying database.
Package redis contains cache implementations using Redis as the underlying database.
Package redis contains cache implementations using Redis as the underlying database.
Package tracing contains middlewares that will add spans to existing traces.
Package tracing contains middlewares that will add spans to existing traces.

Jump to

Keyboard shortcuts

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