Authentication and authorization

This section explains the concepts of authentication and authorization with respect to the Fleet Engine implementation. It details the procedures you need to perform to secure your Fleet Engine function calls.

You can configure capabilities provided by Last Mile Fleet Solution through the Google Cloud Console. These APIs and SDKs require the use of JSON Web Tokens (JWTs) that have been signed using service accounts created from Cloud Console.

Overview

As part of its authorization mechanism, Fleet Engine provides extra security from calls that originate from low-trust environments. Low-trust environments include smartphones and browsers. Additionally, Fleet Engine employs the Principle of least privilege, where a call should be given only those privileges needed for it to complete its task.

To safeguard function calls that originate from low-trust environments, Google designed a mechanism in which your code creates a token on your backend server, which is a fully-trusted environment. Each call carries a complete security description which is then encrypted into a JWT that you pass with the call from any environment.

Authentication design principles

Fleet Engine's authentication flow incorporates the following design principles.

  • IAM roles define the scope of allowed activity for the caller. For example, the SuperUser role is allowed to do everything, whereas the Untrusted Driver role is only allowed to perform minimal location updates.

  • IAM roles are associated with service accounts.

  • JWT claims further restrict the entities that the caller may operate on. These can be specific tasks or delivery vehicles.

  • Requests sent to Fleet Engine always contain a JWT.

    • Since JWTs are associated with service accounts, requests sent to Fleet Engine are implicitly associated with the service account associated with the JWT.
  • In order to request the appropriate JWT that you can then pass to Fleet Engine, your code running in a low-trust environment must first call on your code running in a fully trusted environment.

  • Fleet Engine performs the following security checks:

    1. IAM roles associated with the service account provide the correct authorization for the caller to issue the API call.

    2. The JWT claims passed in the request provide the correct authorization for the caller to operate on the entity.

Authentication flow

The following sequence diagram demonstrates these authentication flow details.

  1. The fleet administrator creates service accounts.

  2. The fleet administrator assigns specific IAM roles to the service accounts.

  3. The fleet administrator configures their backend with the service accounts.

  4. The client app requests a JWT from the partner's backend. The requester could be the Driver app, the Consumer app, or a monitoring app.

  5. Fleet Engine issues a JWT for the respective service account. The client app receives the JWT.

  6. The client app uses the JWT to connect to Fleet Engine to read or modify data, depending on the IAM roles assigned to it during setup phase.

Authentication sequence diagram

Cloud project setup

To set up your cloud project, first create your project and then create service accounts.

To create your Google Cloud project:

  1. Create a Google Cloud Project using the Google Cloud Console.
  2. Using the APIs and Services Dashboard, enable the Local Rides and Deliveries API.

Service Accounts & IAM Roles

A service account is a special kind of account that is used by an application, rather than a person. Typically, a service account is used to mint JWTs that grant different sets of permissions depending on the role. To reduce the possibility of abuse you can create multiple service accounts, each with the minimum set of roles required.

Last Mile Fleet Solution uses the following roles:

RoleDescription
Fleet Engine Delivery Trusted Driver User

roles/fleetengine.deliveryTrustedDriver
Grants permission to create and update delivery vehicles and tasks, including updating the delivery vehicle location and task status or outcome. Tokens minted by a service account with this role are typically used from your delivery driver's mobile devices or from your backend servers.
Fleet Engine Delivery Untrusted Driver User

roles/fleetengine.deliveryUntrustedDriver
Grants permission to update delivery vehicle location. Tokens minted by a service account with this role are typically used from your delivery driver's mobile devices.
Fleet Engine Delivery Consumer User

roles/fleetengine.deliveryConsumer
Grants permission to search for tasks using a tracking ID, and to read but not update task information. Tokens minted by a service account with this role are typically used from a delivery consumer's web browser.
Fleet Engine Delivery Super User

roles/fleetengine.deliverySuperUser
Grants permission to all delivery vehicles and tasks APIs. Tokens minted by a service account with this role are typically used from your backend servers.
Fleet Engine Delivery Fleet Reader

roles/fleetengine.deliveryFleetReader
Grants permission to read delivery vehicles and tasks and to search for tasks using a tracking ID. Tokens minted by a service account with this role are typically used from a delivery fleet operator's web browser.

Organizations that furnish their delivery drivers with devices managed by corporate IT can take advantage of the flexibility offered by the Fleet Engine Trusted Driver User role and choose to integrate some or all of the Fleet Engine interactions in the mobile app.

Organizations supporting Bring Your Own Device policies should opt for the safety of the Fleet Engine Untrusted Driver User role and only rely on the mobile app to send vehicle location updates to Fleet Engine. All other interactions should originate from the customer backend servers.

The Driver and Consumer SDKs are built around these standard roles. However, it is possible to create custom roles that allow an arbitrary set of permissions to be bundled together. The Driver and Consumer SDKs will display error messages when a required permission is missing. As a result, we strongly recommend using the standard set of roles presented above instead of custom roles.

Creating a Service Account

You can create a service account using the IAM & Admin > Service Accounts tab in the Google Cloud Console. From the Role drop-down list, select Fleet Engine and assign one of the roles to the service account. It is good practice to indicate the account that is associated with each role. For example, give the service account a meaningful name.

For convenience, if you need to mint JWTs for untrusted clients, adding users to the Service Account Token Creator Role lets them mint tokens with gcloud command line tools.

gcloud projects add-iam-policy-binding project-id \
       --member=user:my-user@example.com \
       --role=roles/iam.serviceAccountTokenCreator

Where my-user@example.com is the email used to authenticate with gcloud (gcloud auth list --format='value(account)').

Fleet Engine Auth Library

Fleet Engine uses JWTs to restrict access to Fleet Engine APIs. The new Fleet Engine Auth Library, available on Github, simplifies construction of Fleet Engine JWTs and securely signs them.

The library provides the following benefits:

  • Simplifies the process of creating Fleet Engine Tokens.
  • Provides token signing mechanisms other than using credential files (such as impersonating a service account.)
  • Attaches signed tokens to outbound requests made from either a gRPC stub or GAPIC client.

Creating a JSON Web Token (JWT) for authorization

When not using the Fleet Engine Auth Library, JWTs need to be crafted directly within your codebase. This requires you to have both a deep understanding of JWTs and how they relate to Fleet Engine. This is why we HIGHLY recommend taking advantage of the Fleet Engine Auth Library.

Within Fleet Engine, JWTs provide short-lived authentication and ensure that devices may only modify vehicles or tasks for which they are authorized. JWTs contain a header and a claim section. The header section contains information such as the private key to use (obtained from service accounts) and the encryption algorithm. The claim section contains information such as the token's create time, the token's time to live, the services that the token is claiming access to, and other authorization information to scope down access; for example, the delivery vehicle ID.

A JWT header section contains the following fields:

FieldDescription
alg The algorithm to use. `RS256`.
typ The type of token. `JWT`.
kid Your service account's private key ID. You can find this value in the `private_key_id` field of your service account JSON file. Make sure to use a key from a service account with the correct level of permissions.

A JWT claims section contains the following fields:

FieldDescription
iss Your service account's email address.
sub Your service account's email address.
aud Your service account's SERVICE_NAME, in this case https://fleetengine.googleapis.com/
iat The timestamp when the token was created, specified in seconds elapsed since 00:00:00 UTC, January 1, 1970. Allow 10 minutes for skew. If the timestamp is too far in the past, or in the future, the server might report an error.
exp The timestamp when the token expires, specified in seconds elapsed since 00:00:00 UTC, January 1, 1970. The request fails if the timestamp is more than one hour in the future.
authorization Depending on the use case, may contain `deliveryvehicleid`, `trackingid`, `taskid`, or `taskids`.

Minting a JWT token refers to signing it. For instructions and code samples for creating and signing the JWT, see Service account authorization without OAuth. You can then attach a minted token to gRPC calls or other methods used to access Fleet Engine.

JWT Claims

Last Mile Fleet Solution uses private claims. Using private claims ensures that only authorized clients can access their own data. For example, when your backend issues a JSON Web Token for a delivery driver's mobile device, that token should contain the deliveryvehicleid claim with the value of that driver's delivery vehicle ID. Then, depending on the driver role, tokens enable access only for the specific deliver vehicle ID and not any other arbitrary vehicle ID.

Last Mile Fleet Solution uses the following private claims:

  • deliveryvehicleid - use when calling per-delivery-vehicle APIs.
  • taskid - use when calling per-task APIs.
  • taskids - use when calling BatchCreateTasksAPI. This claim must be in array form, and the array should contain all task IDs necessary to complete the request. Do not include delivervehicleid, trackingid, or taskid claims.
  • trackingid - use when calling the SearchTasksAPI. The claim must match the tracking ID in the request. Do not include delivervehicleid, taskid, or taskids claims.

The token must also contain the appropriate claim when you are calling APIs from your backend server, but you can use the special value of an asterisk ("*") for deliveryvehicleid, taskid, and trackingid claims. The asterisk ("*") may also be used in the taskids claim, but it must be the only element in the array.

If you want to create and sign a JSON directly as a token bearer, rather than using OAuth 2.0 access tokens, read the instructions for Service account authorization without OAuth in the Identity Developer documentation.

The mechanism for attaching the token to a gRPC call depends on the language and framework used for making the call. The mechanism for specifying a token to an HTTP call is to include an Authorization header with a bearer token whose value is the token, as noted in the authorization notes for individual shipment tracking or fleet performance use cases.

The following example shows a token for a per-task operation from your backend server:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_provider_service_account"
    }
    .
    {
      "iss": "provider@yourgcpproject.iam.gserviceaccount.com",
      "sub": "provider@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "taskid": "*"
       }
    }

The following example shows a token for a batch create tasks operation from your backend server:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_provider_service_account"
    }
    .
    {
      "iss": "provider@yourgcpproject.iam.gserviceaccount.com",
      "sub": "provider@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "taskids": ["*"]
       }
    }

The following example shows a token for a per-delivery-vehicle operation from your backend server:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_provider_service_account"
    }
    .
    {
      "iss": "provider@yourgcpproject.iam.gserviceaccount.com",
      "sub": "provider@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "deliveryvehicleid": "*"
       }
    }

The following example shows a token for end-user customers:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_delivery_consumer_service_account"
    }
    .
    {
      "iss": "consumer@yourgcpproject.iam.gserviceaccount.com",
      "sub": "consumer@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "trackingid": "shipment_12345"
       }
    }

The following example shows a token for your driver app:

    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "private_key_id_of_delivery_driver_service_account"
    }
    .
    {
      "iss": "driver@yourgcpproject.iam.gserviceaccount.com",
      "sub": "driver@yourgcpproject.iam.gserviceaccount.com",
      "aud": "https://fleetengine.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600,
      "authorization": {
         "deliveryvehicleid": "driver_12345"
       }
    }
  • For the kid field in the header, specify your service account's private key ID. You can find this value in the private_key_id field of your service account JSON file.
  • For the iss and sub fields, specify your service account's email address. You can find this value in the client_email field of your service account JSON file.
  • For the aud field, specify https://SERVICE_NAME/.
  • For the iat field, specify the timestamp when the token was created, in seconds elapsed since 00:00:00 UTC, January 1, 1970. Allow 10 minutes for skew. If the timestamp is too far in the past, or in the future, the server might report an error.
  • For the exp field, specify the timestamp when the token expires, in seconds since 00:00:00 UTC, January 1, 1970. The recommended value is iat + 3600.

When signing the token to be passed to a mobile device or end user, make sure to use the credential file for the Delivery Driver or Consumer role. Otherwise, the mobile device or end user will have the ability to alter or view information they should not have access to.