토큰이란 무엇인가요?
Fleet Engine은 스마트폰 및 브라우저와 같은 신뢰도가 낮은 환경에서 API 메서드 호출 에 JSON 웹 토큰 (JWT)을 사용해야 합니다.
JWT는 서버에서 생성되고 서명, 암호화되어 만료되거나 더 이상 유효하지 않을 때까지 후속 서버 상호작용을 위해 클라이언트에 전달됩니다.
주요 세부정보
- 애플리케이션 기본 사용자 인증 정보를 사용하여 Fleet Engine에 대해 인증하고 승인합니다.
- 적절한 서비스 계정을 사용하여 JWT에 서명합니다. Fleet Engine 기본사항에서 Fleet Engine 서비스 계정 역할을 참고하세요.
JSON 웹 토큰에 관한 자세한 내용은 JSON 웹 토큰을(를) Fleet Engine 필수사항에서 참고하세요.
클라이언트가 토큰을 가져오는 방법
운전자 또는 소비자가 적절한 인증 사용자 인증 정보를 사용하여 앱에 로그인하면 해당 기기에서 발급된 모든 업데이트는 Fleet Engine에 앱 권한을 전달하는 적절한 승인 토큰을 사용해야 합니다.
개발자는 클라이언트 구현에서 다음 작업을 실행할 수 있는 기능을 제공해야 합니다.
- 서버에서 JSON 웹 토큰을 가져옵니다.
- 토큰 새로고침을 최소화하기 위해 토큰이 만료될 때까지 재사용합니다.
- 토큰이 만료되면 새로고침합니다.
GMTDAuthorization 프로토콜은 GMTD AuthorizationContext 객체를 기반으로 위치 업데이트 시간에 JSON 웹 토큰을 가져옵니다. SDK는 Fleet Engine으로 전송할 업데이트 정보와 함께 토큰을 패키징해야 합니다.
SDK를 초기화하기 전에 서버 측 구현에서 토큰을 발급할 수 있는지 확인합니다.
Fleet Engine에서 예상하는 토큰에 관한 자세한 내용은 Fleet Engine용 JSON 웹 토큰 발급을 참고하세요.
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