トークンとは
低信頼環境からの API メソッド呼び出しの場合、Fleet Engine では、適切なサービス アカウントで署名された JSON Web Token(JWT)を使用する必要があります。信頼性の低い環境には、スマートフォンやブラウザが含まれます。JWT の送信元は、完全に信頼できる環境であるサーバーです。JWT は署名され、暗号化されて、有効期限が切れるか無効になるまで、その後のサーバー インタラクションのためにクライアントに渡されます。
バックエンドは、標準のアプリケーションのデフォルト認証情報メカニズムを使用して、Fleet Engine に対して認証と承認を行う必要があります。適切なサービス アカウントで署名された JWT を使用してください。サービス アカウントのロールのリストについては、Fleet Engine の基本の Fleet Engine サービス アカウントのロールをご覧ください。
これに対して、バックエンドでは、標準のアプリケーションのデフォルト認証情報のメカニズムを使用して Fleet Engine に対する認証と認可を行う必要があります。
JSON Web Token の詳細については、Fleet Engine の基本の JSON Web Token をご覧ください。
クライアントがトークンを取得する方法
ドライバーまたはユーザーが適切な認証情報を使用してアプリにログインすると、そのデバイスから発行される更新では、適切な認可トークンを使用する必要があります。このトークンは、アプリの権限を Fleet Engine に通知します。
デベロッパーは、クライアントの実装で次の機能を提供する必要があります。
- サーバーから JSON Web Token を取得します。
- 有効期限が切れるまでトークンを再利用して、トークンの更新を最小限にします。
- トークンの有効期限が切れたときにトークンを更新します。
GMTDAuthorization
プロトコルは、位置情報の更新時に GMTD AuthorizationContext
オブジェクトに基づいて JSON Web Token を取得します。SDK は、Fleet Engine に送信する更新情報とともにトークンをパッケージ化する必要があります。SDK を初期化する前に、サーバーサイドの実装でトークンを発行できることを確認してください。
Fleet Engine で想定されるトークンの詳細については、Fleet Engine の JSON Web Token を発行するをご覧ください。
providerID は、Google Cloud プロジェクトのプロジェクト ID と同じです。Google Cloud プロジェクトの設定については、Fleet Engine プロジェクトを作成するをご覧ください。
認証トークン フェッチャーの例
次の例は、GMTDAuthorization
プロトコルの実装を示しています。
Swift
import GoogleRidesharingDriver
private let providerURL = "INSERT_YOUR_TOKEN_PROVIDER_URL"
class SampleAccessTokenProvider: NSObject, GMTDAuthorization {
private struct AuthToken {
// The cached vehicle token.
let token: String
// Keep track of when the token expires for caching.
let expiration: TimeInterval
// Keep track of the vehicle ID the cached token is for.
let vehicleID: String
}
enum AccessTokenError: Error {
case missingAuthorizationContext
case missingData
}
private var authToken: AuthToken?
func fetchToken(
with authorizationContext: GMTDAuthorizationContext?,
completion: @escaping GMTDAuthTokenFetchCompletionHandler
) {
// Get the vehicle ID from the authorizationContext. This is set by the Driver SDK.
guard let authorizationContext = authorizationContext else {
completion(nil, AccessTokenError.missingAuthorizationContext)
return
}
let vehicleID = authorizationContext.vehicleID
// If appropriate, use the cached token.
if let authToken = authToken,
authToken.expiration > Date.now.timeIntervalSince1970 && authToken.vehicleID == vehicleID
{
completion(authToken.token, nil)
return
}
// Otherwise, try to fetch a new token from your server.
let request = URLRequest(url: URL(string: providerURL))
let task = URLSession.shared.dataTask(with: request) { [weak self] data, _, error in
guard let strongSelf = self else { return }
guard error == nil else {
completion(nil, error)
return
}
// Replace the following key values with the appropriate keys based on your
// server's expected response.
let vehicleTokenKey = "VEHICLE_TOKEN_KEY"
let tokenExpirationKey = "TOKEN_EXPIRATION"
guard let data = data,
let fetchData = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let token = fetchData[vehicleTokenKey] as? String,
let expiration = fetchData[tokenExpirationKey] as? Double
else {
completion(nil, AccessTokenError.missingData)
return
}
strongSelf.authToken = AuthToken(
token: token, expiration: expiration, vehicleID: vehicleID)
completion(token, nil)
}
task.resume()
}
}
Objective-C
#import "SampleAccessTokenProvider.h"
#import <GoogleRidesharingDriver/GoogleRidesharingDriver.h>
// SampleAccessTokenProvider.h
@interface SampleAccessTokenProvider : NSObject<GMTDAuthorization>
@end
static NSString *const PROVIDER_URL = @"INSERT_YOUR_TOKEN_PROVIDER_URL";
// SampleAccessTokenProvider.m
@implementation SampleAccessTokenProvider{
// The cached vehicle token.
NSString *_cachedVehicleToken;
// Keep track of the vehicle ID the cached token is for.
NSString *_lastKnownVehicleID;
// Keep track of when tokens expire for caching.
NSTimeInterval _tokenExpiration;
}
- (void)fetchTokenWithContext:(nullable GMTDAuthorizationContext *)authorizationContext
completion:(nonnull GMTDAuthTokenFetchCompletionHandler)completion {
if (!completion) {
NSAssert(NO, @"%s encountered an unexpected nil completion.", __PRETTY_FUNCTION__);
return;
}
// Get the vehicle ID from the authorizationContext. This is set by the Driver SDK.
NSString *vehicleID = authorizationContext.vehicleID;
if (!vehicleID) {
NSAssert(NO, @"Vehicle ID is missing from authorizationContext.");
return;
}
// Clear cached vehicle token if vehicle ID has changed.
if (![_lastKnownVehicleID isEqual:vehicleID]) {
_tokenExpiration = 0.0;
_cachedVehicleToken = nil;
}
_lastKnownVehicleID = vehicleID;
// Clear cached vehicletoken if it has expired.
if ([[NSDate date] timeIntervalSince1970] > _tokenExpiration) {
_cachedVehicleToken = nil;
}
// If appropriate, use the cached token.
if (_cachedVehicleToken) {
completion(_cachedVehicleToken, nil);
return;
}
// Otherwise, try to fetch a new token from your server.
NSURL *requestURL = [NSURL URLWithString:PROVIDER_URL];
NSMutableURLRequest *request =
[[NSMutableURLRequest alloc] initWithURL:requestURL];
request.HTTPMethod = @"GET";
// Replace the following key values with the appropriate keys based on your
// server's expected response.
NSString *vehicleTokenKey = @"VEHICLE_TOKEN_KEY";
NSString *tokenExpirationKey = @"TOKEN_EXPIRATION";
__weak typeof(self) weakSelf = self;
void (^handler)(NSData *_Nullable data, NSURLResponse *_Nullable response,
NSError *_Nullable error) =
^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
typeof(self) strongSelf = weakSelf;
if (error) {
completion(nil, error);
return;
}
NSError *JSONError;
NSMutableDictionary *JSONResponse =
[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&JSONError];
if (JSONError) {
completion(nil, JSONError);
return;
} else {
// Sample code only. No validation logic.
id expirationData = JSONResponse[tokenExpirationKey];
if ([expirationData isKindOfClass:[NSNumber class]]) {
NSTimeInterval expirationTime = ((NSNumber *)expirationData).doubleValue;
strongSelf->_tokenExpiration = [[NSDate date] timeIntervalSince1970] + expirationTime;
}
strongSelf->_cachedVehicleToken = JSONResponse[vehicleTokenKey];
completion(JSONResponse[vehicleTokenKey], nil);
}
};
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *mainQueueURLSession =
[NSURLSession sessionWithConfiguration:config delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [mainQueueURLSession dataTaskWithRequest:request completionHandler:handler];
[task resume];
}
@end