github.com/wostzone/hub/auth@v0.0.0-20220118060317-7bb375743b17/README.md (about)

     1  # hubauth
     2  
     3  ## Objective
     4  
     5  Single sign-on with access control for users to access Hub services.
     6  
     7  ## Status
     8  
     9  The status of this plugin is alpha. It is functional but breaking changes are expected.
    10  
    11  ## Audience
    12  
    13  This project is aimed at IoT developers that value the security and interoperability that WoST brings. WoST Things are
    14  more secure than traditional IoT devices as they do not run a server, but instead connect to a Hub to publish their
    15  information and receive actions.
    16  
    17  ## Summary
    18  
    19  This service provides authentication and authorization for services and their clients. All requests to the various Hub
    20  services requires authentication by the Auth service.
    21  
    22  Login provides the user with a pair of JWT tokens that can be used to authenticate at all services. Access tokens have a
    23  short lifetime and must be refreshed using the refresh token before they expire.
    24  
    25  This provides a
    26  
    27  * Authentication service for...
    28      * Providing access and refresh tokens using the users login credentials
    29      * Refreshing user access/refresh token pair
    30      * Creating username/password by administrator
    31      * Changing of the user password
    32  
    33  * Library for validating access token by services
    34  
    35  * Commandline utility to manage users, change passwords (by administrator) and generate certificates.
    36  
    37  ### Certificate Generation
    38  
    39  The hubauth module generates the following certificates and stores then in the Hub 'certs' folder.
    40  
    41  1. The CA certificate and private key is generated on first startup, as a self-signed certificate. The CA certficate is
    42     shared with every client and server and is used to verify authenticity of all other certificates. The CA key is only
    43     used to generate the certificates listed here. Intermediary certificates are not used by WoST Hub services.
    44  2. The hub certificate and key are regenerated on each startup using the CA certificate. This certificate is used by hub
    45     services such as the provisioning server (idprov), directory server (thingdir), and mosquitto message bus server. The
    46     keys of this certificate is used to generate and validate access and refresh tokens.
    47  3. The plugin certificate and key are regenerated on each startup using the CA certificate. This client certificate is
    48     used by hub services to authenticate access other hub services, like for example the message bus.
    49  4. IoT Device client certificates are generated by the IDProv provisioning server using the client's public key. These
    50     certificates include the OU 'things' and are only issued to IoT devices that publish Thing information.
    51  
    52  A commandline utility can generate custom certificates for special users such as administrators. All services accept
    53  certificates signed by the CA.
    54  
    55  ### Client Certificate Authentication
    56  
    57  Authentication through client certificates is handled by the TLS protocol itself. A valid certificate is required in
    58  order to make a connection. The certificate CN contains the user or service name, the OU is used to indicate the role in
    59  the organization.
    60  
    61  * Hub plugins use the hub client certificate to access other Hub services. The Hub plugin certificate contains 'plugin'
    62    as the OU which is used to authorize full access.
    63  * IoT devices have the device-ID as the CN and 'iotdevice' as the OU. IoT devices are publishers of things and have
    64    access to all Things of which they are the publisher.
    65  * The administrator certificate has their user loginID as the CN and 'admin' as the OU.
    66  * Other clients have their loginID as the CN and 'client' as the OU.
    67  
    68  Properly signed certificates are always accepted as valid authentication. Their OU are used in authorization.
    69  
    70  ### Username/password Authentication
    71  
    72  Unpw authentication is used for users that connect through a web client or mobile application. Clients use the auth API
    73  with their login ID and password to obtain a pair of tokens that are needed to use the service API. To change a password
    74  a valid password is also needed.
    75  
    76  Administrators manage users and passwords through the 'auth' commandline utility or through the auth API. Creating users
    77  or resetting passwords requires an 'admin' client certificate authentication.
    78  
    79  #### **Password Storage**
    80  
    81  Passwords are stored by the service using argon2id hashing. This is chosen as it is one of the strongest hash algorithms
    82  that is resistant to GPU cracking attacks and side channel
    83  attacks. [See wikipedia](https://en.wikipedia.org/wiki/Argon2). In future other algorithms can be supported as needed.
    84  
    85  #### **Token Generation**
    86  
    87  Unpw authentication uses JWT with H256 hashing for access and refresh token generation. Hashing protocol negotiation is
    88  not
    89  allowed [as this is considered a weakness](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/)
    90  . The required hashing algorithm can be changed without notice but is dictated by the server. JWT is chosen as it
    91  secures a set of 'claims' which includes the userID. The userID is needed for authorization of a request. The hub
    92  private key is used as the secret shared amongst plugin services. It is regenerated on each restart of the hub (
    93  requiring a new login). The JWT header includes the hashing algorithm which MUST match the algorithm service is
    94  configured for before token verification takes place.
    95  
    96  Clients request an access/refresh token-pair from the auth service endpoint by providing a login ID and a secret (
    97  password). The refresh token can be used to obtain a new set of access/refresh tokens. This approach allows for
    98  stateless verification of the access token for its (configurable) validity period with a default of 1 hour. The refresh
    99  token is valid for a longer with a default of two weeks. After the token expires, the user has to login to obtain a new
   100  token pair. Until then no login is required. Refresh tokens are stored in secure client cookies which means they are not
   101  accessible by clients and each applicatino must must login separately. Once logged in refresh tokens are used to avoid
   102  unnecesary logins.
   103  
   104  Access and refresh tokens include claim with the IP address of the sender, which must match during verification. Any
   105  attempt to use the tokens with a different IP fails. The refresh token will be invalidated if an IP mismatch is detected
   106  even if it hasn't expired yet.
   107  
   108  All Hub services accept the access token within its validity period. Services verify the access token and its claims
   109  using the server certificate key which all services have access to. Since a restart of the hub regenerates this key,
   110  access and refresh tokens are invalidated at a Hub restart.
   111  
   112  In short, services perform stateless verification of access tokens and return unauthorized if the token is expired or
   113  doesn't match the IP address of the sender. Clients must refresh their tokens if they receive an unauthorized response
   114  from one of the services and retry the request.
   115  
   116  Weakness: Access to the tokens is the achilles heel of this approach. If a bad actor obtains a token while it is still
   117  valid, and can spoof its IP address to that of the token, then security is compromised.
   118  
   119  ## Authorization
   120  
   121  The auth module provides a library to assist services with handling authorizing requests.
   122  
   123  Hub authorization groups things together and lets users view or control those things. This makes is easy to give
   124  multiple users access to the same set of Things and at the same time simplifies access management of things.
   125  
   126  Hub authorization is based on roles in groups that are centrally managed by the auth module:
   127  
   128  1. Plugins have full authorization and access to all Things on the Hub
   129  2. Users only have access to Things in the same group, based on their role:
   130      - view role gives read access to Things
   131      - control role lets the user control things
   132      - manage role lets the user configure things
   133      - admin role has full access
   134      - thing role is for things only and lets the thing manage itself
   135  
   136  The 'all' group is built-in and automatically includes all Things. To allow a user to view all Things, the loginID is
   137  added to the all group with the 'view' role.
   138  
   139  A future considerations is to automatically create groups based on Thing Type, for example a group of environmental
   140  sensors. This further simplifies group creation as things are automatically added to the groups they serve. This
   141  requires a good consistent vocabulary of Thing types which is still tbd.
   142  
   143  ### Group Management
   144  
   145  Things, users, groups and roles are defined in the ACL store. The first store implementation is a file that is loaded in
   146  memory. The auth commandline lets the administrator add and remove users from the group. A REST API for managing groups
   147  is planned.
   148  
   149  The client library automatically reloads the file if it is modified.
   150  
   151  To authorize a request, the client library needs to know the login-ID of the user, thing-ID to access, read/write
   152  operation to perform and in case of writing the message type to write. These write message types are the Thing
   153  Description document (TD), values update, action, event, and configuration.
   154  
   155  The role permissions for these actions are:
   156  
   157  | Role   |  TD   | Configure | Values  |  Event | Action
   158  |--------|-------| --------- | ------- | -------| -------
   159  | view   | read  | -         | read    | read   | -
   160  | control| read  | -         | read    | read   | write
   161  | manage | read  | write     | read    | read   | write
   162  | admin  | read  | write     | read    | read   | write
   163  | thing  | write | read      | write   | write  | write
   164  | plugin | write | write     | write   | write  | write
   165  
   166  ## Build and Installation
   167  
   168  ### Build & Install (tentative)
   169  
   170  Run 'make all' to build and 'make install' to install as a user.
   171  
   172  See [hub's README.md](https://github.com/wostzone/hub/README.md) for more details.
   173  
   174  ## Usage
   175  
   176  Code below is pseudocode and needs to be updated.
   177  
   178  ### User login
   179  
   180  ```golang
   181    authClient := NewAuthClient(address, port)
   182  accessToken, err := authClient.Login(username, password)
   183  // login sets the refresh token in a secure cookie. 
   184  ```
   185  
   186  ### User refresh auth tokens
   187  
   188  ```golang
   189    authClient := NewAuthClient(address, port)
   190  // The refresh token was stored in a secure cookie. 
   191  accessToken, err := authClient.Refresh()
   192  if err != nil {
   193  // if token cannot be refreshed then request user login    
   194  }
   195  ```
   196  
   197  ### Server validates token (authenticate)
   198  
   199  Access tokens can be validated stateless as long as we know to verification secret
   200  
   201  ```golang
   202    secret := ReadPrivateKey(file)
   203  authClient := NewAuthClient(secret)
   204  claims, err := authClient.VerifyToken(accessToken)
   205  if err != nil {
   206  return unauthorized
   207  }
   208  ```
   209  
   210  ### Server authorizes user
   211  
   212  Authorization keeps the ACL store in memory.
   213  
   214  * loginID is the user login ID when authenticated with password
   215  * ou is the user OU when authenticated using a client certificate
   216  * thingID is the thing to access
   217  * writing is read (false) or write (true) access
   218  * writeType is the type of record to write, eg TD, Action, Event, Config, ...
   219  
   220  ```golang
   221    thing1ID := "urn:zone1:publisher1:thing1"
   222  loginID := "user1"
   223  ou := ""   // from client certificate if used
   224  writing := false
   225  writeType := MessageTypeTD
   226  aclStore := aclstore.NewAclFileStore(aclFilePath, PluginID)
   227  az := authorize.NewAuthorizer(aclStore)
   228  az.VerifyAuthorization(loginID, ou, thingID, writing, writeType)
   229  ```
   230  
   231  ### Administrator adds user to group
   232  
   233  To allow a user to view things in group 'temperature'
   234  
   235  ```golang
   236    groupName := "temperature"
   237  aclStore := aclstore.NewAclFileStore(aclFilePath, PluginID)
   238  aclStore.SetRole(loginID, groupName, authorize.GroupRoleViewer)
   239  ```
   240  
   241  Or editing the acl file directly:
   242  
   243  > groups.yaml
   244  
   245  ```yaml
   246  all:
   247    admin: GroupRoleManager
   248  
   249  temperature:
   250    user1: GroupRoleViewer
   251    urn:zone1:publisher1:thing1: ThingRole
   252    urn:zone1:publisher1:thing2: ThingRole
   253  ```