github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/docs/v2/design/framework/auth.md (about) 1 # Authentication 2 3 Micro needs an authentication story. In the beginning go-micro had no auth, on the premise that the base requirement 4 for distributed systems was solely discovery and communication. Our default experience will continue to operate 5 in a zero auth noop model until we can identify how zero trust will work. 6 7 ## Overview 8 9 Auth will include both authentication and authorization. Authentication is the basis for checking whether a user 10 or service is "logged in" or has an access token to use across the system. Authorization is used to check 11 whether a user or service actually has the privileges to access a resource. 12 13 Our story always begins with 14 15 - go-micro interface with implementations 16 * zero dep default experience 17 * industry standard highly available system 18 * micro rpc service implementation 19 20 The go-micro interface should interop with the rest of the framework then have the capability of being swapped 21 out in production for a centralised system. The micro service implemenation enables an anti corruption layer 22 to abstract away the underlying infrastructure and further usage through the surrounding micro ecosystem. 23 24 ## Implemenations 25 26 - Zero dep - likely noop because it does not need to be included by default 27 - Service - go.micro.auth is responsible for managing rules and accounts. 28 - Casbin, Hydra, OPA - these are becoming open source standards for oauth/rbac and make the most sense here 29 30 ## Interface 31 32 The auth interface provides the following methods. Each one is explained in detail below. 33 ```go 34 // Auth providers authentication and authorization 35 type Auth interface { 36 // Initialise the auth implementation. This must be called before any other methods are called. 37 Init(opts ...Option) 38 // Options returns all the options set when initialising the auth implementation, such as credentials etc. 39 Options() Options 40 // Generate creates a new auth account. The only required argument is ID, however roles, metadata and a secret can all be set using the GenerateOptions. Secret is not always required since it wouldn't make sense for some resources such services to have passwords. 41 Generate(id string, opts ...GenerateOption) (*Account, error) 42 // Destroy allows an account to be deleted 43 Destroy(id string) error 44 // RBAC (role based access control) is used for auth. Roles can be provided to an account on Generate as an option. Roles can be granted access to a resource, e.g. grant the role "user.finance" access to any endpoint on the service named "go.micro.service.reporting". 45 Grant(role string, res *Resource) error 46 // The inverse of grant, revoke removes a roles access to a resource. 47 Revoke(role string, res *Resource) error 48 // Verify takes an account and verifies is has access to a resource based on the RBAC rules. The implementation will keep a record of the roles granted access to the resource, it will then compare those roles to the roles given to the user and return an error if a match is not found. 49 Verify(acc *Account, res *Resource) error 50 // Inspect takes an access token (normally a JWT), inspects the token (this can be done client-side if the token is a JWT and the client has access to the public key), and then returns the account which the token was generated for. 51 Inspect(token string) (*Account, error) 52 // Token generates a new token for an account. Tokens contain a short-lived access token, which can be used to perform calls in the system and a long lived refresh token which can later be exchanged for a new token. Token requires some form of authentication, which is provided as a TokenOption, this can either be the accounts credentials (id, secret) or a refresh token which was provided by a previous call to Token. 53 Token(opts ...TokenOption) (*Token, error) 54 // String returns the name of the implementation, e.g. service. 55 String() string 56 } 57 58 // Resource is an entity such a service. RBAC ensures anyone calling this resource has the necessary roles. 59 type Resource struct { 60 // Name of the resource, e.g. "go.micro.store" 61 Name string `json:"name"` 62 // Type of resource, e.g. "service" 63 Type string `json:"type"` 64 // Endpoint of the resource, e.g. "Store.Read". We specify endpoint as this allows us to use RBAC at an endpoint level. '*' can be used as a wilcard to specify any endpoint. 65 Endpoint string `json:"endpoint"` 66 // Namespace the resource belongs to, the default is "micro" (auth.DefaultNamespace). Namespace allows for multi-tenancy RBAC, since there could be multiple versions of "go.micro.store" running in different namespaces. 67 Namespace string `json:"namespace"` 68 } 69 70 // Account is a resource such as a user or a service who needs to make requests and be authenticated by micro. 71 type Account struct { 72 // ID of the account. For users this is normally their email (e.g. 'johndoe@micro.mu') and for services this is normally their name (e.g. 'go.micro.store'). 73 ID string `json:"id"` 74 // Type of the account, e.g. service. Account types should always be lowercase. 75 Type string `json:"type"` 76 // Provider who issued the account, e.g. "oauth/google". This is currentlys used as additional information when auditing the account. 77 Provider string `json:"provider"` 78 // Roles the account was provided with as a GenerateOption. These rules are used when doing RBAC. 79 Roles []string `json:"roles"` 80 // Metadata is a key/value map which can be used to store additonal information about the account, such as their name and avatar. 81 Metadata map[string]string `json:"metadata"` 82 // Namespace the account belongs to. The default is "micro" (auth.DefaultNamespace). This allows for IDs to be scoped to namespace and not need to be globally unique. 83 Namespace string `json:"namespace"` 84 // Secret for the account, e.g. the password or a secret persisted by the accounts provider. 85 Secret string `json:"secret"` 86 } 87 88 // Token contains the credentials needed for an account to perform requests and refresh its identity. 89 type Token struct { 90 // AccessToken is a short lived token provided on each request the account makes. This is either a JWT or a standard token (UUID V4). 91 AccessToken string `json:"access_token"` 92 // RefreshToken is a long lived token which is only used when calling the Token method to generate a new AccessToken. 93 RefreshToken string `json:"refresh_token"` 94 // Created is the time the token was created. 95 Created time.Time `json:"created"` 96 // Expiry is the time the access token will expire. The client will need to call the Token method before this time and replace this token with a new one. 97 Expiry time.Time `json:"expiry"` 98 } 99 ``` 100 101 ## Wrapper 102 103 go-micro/util/wrapper.go contains an `AuthHandler`. This handler wraps all incoming requests and is responsible for authentication and authorization. This wrapper is always enabled, even if MICRO_AUTH is not specified, however the noop implementation will verify all requests. 104 105 The wrapper will return immediately for any requests made against Debug endpoints, which are added to all go-micro services. We may change this in the future and extend RBAC to include Debug. 106 107 ### Token 108 109 The first thing the wrapper does is check for an auth token. This is the `access-token` which is provided in the Token object. This token is passed in context as `Authorization` header and is prefixed by `Bearer ` (auth.BearerScheme). If the cookie `micro-token` is provided, micro web will set this in the context. 110 111 ### Load the account 112 113 The token will be inspected using the auth.Inspect method to determine the account. If no account is retrieved, we fall back on a blank account for the scope of the wrapper, since the noop auth implementation will allow requests through regardless. 114 115 ### Namespace 116 117 When a request enters the platform, micro web / api will determine the namespace. If the request host is micro.mu or any subdomain, the default namespace is used: `micro` (auth.DefaultNamespace). 118 119 If a non-micro domain is used, e.g. `dev.m3o.app`, the subdomain is determined to be the namespace, in this example: `dev`. If a subdomain has not been used, we fall back to the default namespace. 120 121 Micro API / Web will set the namespace in the context using the `auth.NamespaceKey` key. The wrapper will check for this key, or fall back to the default namespace if it is not found. 122 123 The namespace is then compared to the namespace in the account. If the namespaces do not match, a forbidden error is returned and the occurrance logged. 124 125 126 ### RBAC 127 128 Next, the wrapper will call the `auth.Verify` method to determine if the account has access to the resource it's calling. The resource is determined using a combination of the namespace calculated in the previous step, along with the service name / endpoint provided to the wrapper as part of the request. 129 130 If Verify disallows the request, the user is unauthorised and the request is terminated. 131 132 ### Setting the account 133 134 Handlers often need to access the auth account to retrieve data such as account ID, so auth provides two helper methods to enable this: `AccountFromContext` to set the account in the context (used by the wrapper) and `ContextWithAccount` (optionally used by the handler).