LoginSignup
46

More than 5 years have passed since last update.

Firebase HTTPS callable function を試してみる

Last updated at Posted at 2018-03-23

2018年3月20日の Firebase の更新で、クライアントから直接 Cloud Functions が叩ける機能が入りました。
Call Functions from Your App  |  Firebase

認証状態を持ったまま Cloud Functions を叩くことができるので、今までのように authenticated-json-apiauthorized-https-endpoint のような自前の認証は不要になりました。

使ってみる

iOS + Cloud Functions で使ってみました。

Cloud Functions

TypeScript の例です。

export const httpcallable = functions.https.onCall((data, context) => {
    if (!context.auth) {
        throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
            'while authenticated.')
    }

    if (!data.name) {
        console.log('data.name is not found')
        throw new functions.https.HttpsError('invalid-argument', 'data.name is undefined.', data)
    }

    return {
        uid: context.auth!.uid,
        name: data.name,
        data: data,
        context: context
    }
})

Cloud Functions は data, context を受け取ることができます。
data はクライアント側から渡すことのできるパラメータです。

context には認証情報などが含まれています、 context の型をみてみましょう。

export interface CallableContext {
    auth?: {
        uid: string;
        token: firebase.auth.DecodedIdToken;
    };
    instanceIdToken?: string;
}

認証済みだったら auth に値が入ってきます。auth があるか、anonymous かどうかもその内容で判定できます。
実際のパラメータはこのようになっていました。

未ログイン

context { instanceIdToken: 'hogehoge-token' }

anonymous ログイン

context { auth: 
   { uid: 'uid',
     token: 
      { iss: 'https://securetoken.google.com/myproj',
        provider_id: 'anonymous',
        aud: 'myproj',
        auth_time: 1521769673,
        user_id: 'uid',
        sub: 'uid',
        iat: 1521782508,
        exp: 1521786108,
        firebase: [Object],
        uid: 'uid' } },
  instanceIdToken: 'hogehoge-token' }

firebase のなかみ

firebase { identities: {}, sign_in_provider: 'anonymous' }

facebook ログイン

context { auth: 
   { uid: 'uid',
     token: 
      { iss: 'https://securetoken.google.com/myproj',
        name: 'Mike',
        picture: 'https://scontent.xx.fbcdn.net/v/jpg',
        aud: 'myproj',
        auth_time: 1521788688,
        user_id: 'uid',
        sub: 'uid',
        iat: 1521788688,
        exp: 1521792288,
        email: 'hoge@tfbnw.net',
        email_verified: false,
        firebase: [Object],
        uid: 'uid' } },
  instanceIdToken: 'hogehoge-token' }

firebase の中はこんな感じ

firebase { identities: 
   { 'facebook.com': [ '100258...' ],
     email: [ 'hoge@tfbnw.net' ] },
  sign_in_provider: 'facebook.com' }

注意

エラーを返す時は throw しましょう。 return new functions.https.HttpsError('invalid-argument', 'data.name is undefined.', data) だとクライアント側に無が返されます。 (result も error も nil が返る)

エラー

下記のエラー型が定義されています。HTTP Status Code のように使いやすく良いですね。

export declare type FunctionsErrorCode = 
  'ok' | 'cancelled' | 'unknown' | 'invalid-argument' | 
  'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 
  'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' |
  'data-loss' | 'unauthenticated';

iOS

これだけで認証済みで Functions を叩くことができます。便利ですね。

import FirebaseFunctions

functions.httpsCallable("httpcallable").call(["name": "taro"]) { (result, error) in
  if let error = error as NSError? {
    if error.domain == FunctionsErrorDomain {
      let code = FIRFunctionsErrorCode(rawValue: error.code)
      let message = error.localizedDescription
      let details = error.userInfo[FunctionsErrorDetailsKey]
    }
  }
  if let name = (result?.data as? [String: Any])?["name"] as? String {
    print(name)
  }
}

response は result or error になっています。

result.data に Functions が return したデータが入ってきます。
result.context に auth 情報も入っていました。

内部実装はどうなっているか

firebase-functions の内部実装を読んでみると、HTTP で叩いているだけのようです。
ざっくり読んだだけですが、 authorized-https-endpoint をラップしたメソッドを提供してくれているだけのようです、onCall のコードは 50 行程度なので読んでみると良いと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46