The Consumer SDK provides authorization using JSON Web Tokens. A JSON Web Token
(JWT) is an authorization token that provides one or more claims on a service.

The Consumer SDK uses the JSON Web Token provided by the application to
communicate with the Fleet Engine. For details of the tokens expected by the
Fleet Engine server, see [JSON Web Tokens](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/set-up-fleet/jwt.md.txt)
and [Issue JSON Web tokens](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/set-up-fleet/issue-jwt.md.txt).

The authorization token provides access to the following Fleet Engine services:

- **`TripService`** - Gives the Consumer SDK access to trip details, including
  vehicle position, route, and ETA. Authorization tokens for the trip service
  must include a `tripid:TRIP_ID` claim in the token's `authorization` header,
  where `TRIP_ID` is the trip ID of the on-demand trip being shared.

- **`VehicleService`** - Gives the Consumer SDK information about the
  approximate vehicle location for displaying the vehicle density layer and
  estimating pickup point ETAs. Because the Consumer SDK uses only approximate
  locations, authorization tokens for the vehicle service don't require a
  `vehicleid` claim.

## What is a token?

Fleet Engine requires the use of **JSON Web Tokens** (JWTs) for API method calls
from **low-trust environments**: smartphones and browsers.

A JWT originates on your server, is signed, encrypted, and passed to the client
for subsequent server interactions until it expires or is no longer valid.

**Key details**

- Use [Application Default Credentials](https://google.aip.dev/auth/4110) to authenticate and authorize against Fleet Engine.
- Use an appropriate service account to sign JWTs. See [Fleet Engine serviceaccount](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/set-up-fleet/service-accounts.md.txt#fleet_engine_service_account_roles) roles in **Fleet Engine Basics**.

For more information about JSON Web Tokens, see [JSON Web Tokens](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/set-up-fleet/jwt.md.txt) in
**Fleet Engine Essentials**.

## How do clients get tokens?

Once a driver or consumer logs in to your app using the appropriate
authorization credentials, any updates issued from that device must use
appropriate authorization tokens, which communicates to Fleet Engine the
permissions for the app.

As the developer, your client implementation should provide the ability to do
the following:

- Fetch a JSON Web Token from your server.
- Reuse the token until it expires to minimize token refreshes.
- Refresh the token when it expires.

The `AuthTokenFactory` class generates authorization tokens at location update
time. The SDK must package the tokens with the update
information to send to Fleet Engine. Make sure that your server-side
implementation can issue tokens before initializing the SDK.

For details of the tokens expected by the Fleet Engine service, see [Issue JSON
Web Tokens](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/set-up-fleet/issue-jwt) for Fleet Engine.

## Example of an authorization token fetcher

The following code example demonstrates how to implement an authorization token
callback.

### Java

```java
class JsonAuthTokenFactory implements AuthTokenFactory {

  private static final String TOKEN_URL =
      "https://yourauthserver.example/token";

  private static class CachedToken {
    String tokenValue;
    long expiryTimeMs;
    String tripId;
  }

  private CachedToken token;

  /*

*   This method is called on a background thread. Blocking is OK. However, be
*   aware that no information can be obtained from Fleet Engine until this
*   method returns.
*/
@Override
public String getToken(AuthTokenContext context) {
  // If there is no existing token or token has expired, go get a new one.
  String tripId = context.getTripId();
  if (tripId == null) {
    throw new RuntimeException("Trip ID is missing from AuthTokenContext");
  }
  if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
      !tripId.equals(token.tripId)) {
    token = fetchNewToken(tripId);
  }
  return token.tokenValue;
}

  private static CachedToken fetchNewToken(String tripId) {
    String url = TOKEN_URL + "/" + tripId;
    CachedToken token = new CachedToken();

    try (Reader r = new InputStreamReader(new URL(url).openStream())) {
      com.google.gson.JsonObject obj
          = com.google.gson.JsonParser.parseReader(r).getAsJsonObject();

      token.tokenValue = obj.get("ServiceToken").getAsString();
      token.expiryTimeMs = obj.get("TokenExpiryMs").getAsLong();

      /*

    *   The expiry time could be an hour from now, but just to try and avoid
    *   passing expired tokens, we subtract 5 minutes from that time.
    */
    token.expiryTimeMs -= 5 * 60 * 1000;
  } catch (IOException e) {
    /*
    *   It's OK to throw exceptions here. The error listeners will receive the
    *   error thrown here.
    */
    throw new RuntimeException("Could not get auth token", e);
  }
  token.tripId = tripId;

    return token;
  }
}
```

### Kotlin

```kotlin
class JsonAuthTokenFactory : AuthTokenFactory() {

  private var token: CachedToken? = null

  /*

*   This method is called on a background thread. Blocking is OK. However, be
*   aware that no information can be obtained from Fleet Engine until this
*   method returns.
*/
override fun getToken(context: AuthTokenContext): String {
  // If there is no existing token or token has expired, go get a new one.
  val tripId =
    context.getTripId() ?:
      throw RuntimeException("Trip ID is missing from AuthTokenContext")

    if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
        tripId != token.tripId) {
      token = fetchNewToken(tripId)
    }

    return token.tokenValue
  }

  class CachedToken(
    var tokenValue: String? = "",
    var expiryTimeMs: Long = 0,
    var tripId: String? = "",
  )

  private companion object {
    const val TOKEN_URL = "https://yourauthserver.example/token"

    fun fetchNewToken(tripId: String) {
      val url = "$TOKEN_URL/$tripId"
      val token = CachedToken()

      try {
        val reader = InputStreamReader(URL(url).openStream())

        reader.use {
          val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()

          token.tokenValue = obj.get("ServiceToken").getAsString()
          token.expiryTimeMs = obj.get("TokenExpiryMs").getAsLong()

          /*

        *   The expiry time could be an hour from now, but just to try and avoid
        *   passing expired tokens, we subtract 5 minutes from that time.
        */
        token.expiryTimeMs -= 5 * 60 * 1000
      }
    } catch (e: IOException) {
      /*
            *   It's OK to throw exceptions here. The error listeners will receive the
            *   error thrown here.
      */
      throw RuntimeException("Could not get auth token", e)
    }

      token.tripId = tripId

      return token
    }
  }
}
```

## What's next

[Initialize the Consumer SDK](https://developers.google.com/maps/documentation/mobility/journey-sharing/on-demand/android/init-sdk.md.txt)