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).