Skip to content

Hack App Check API to test the REGAPIC client #566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions firebase_admin/_token_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
MAX_TOKEN_LIFETIME_SECONDS = int(datetime.timedelta(hours=1).total_seconds())
FIREBASE_AUDIENCE = ('https://identitytoolkit.googleapis.com/google.'
'identity.identitytoolkit.v1.IdentityToolkit')
FIREBASE_APP_CHECK_AUDIENCE = ('https://firebaseappcheck.googleapis.com/google.'
'firebase.appcheck.v1beta.TokenExchangeService')
RESERVED_CLAIMS = set([
'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash',
'exp', 'firebase', 'iat', 'iss', 'jti', 'nbf', 'nonce', 'sub'
Expand Down Expand Up @@ -206,6 +208,31 @@ def create_custom_token(self, uid, developer_claims=None, tenant_id=None):
raise TokenSignError(msg, error)


def create_custom_token_fac(self, app_id):
"""Builds and signs a Firebase custom FAC token."""

if not app_id or not isinstance(app_id, str):
raise ValueError('app_id must be a string.')

signing_provider = self.signing_provider
now = int(time.time())
payload = {
'iss': signing_provider.signer_email,
'sub': signing_provider.signer_email,
'aud': FIREBASE_APP_CHECK_AUDIENCE,
'app_id': app_id,
'iat': now,
'exp': now + MAX_TOKEN_LIFETIME_SECONDS,
}

header = {'alg': signing_provider.alg, 'typ': 'JWT'}
try:
return jwt.encode(signing_provider.signer, payload, header=header)
except google.auth.exceptions.TransportError as error:
msg = 'Failed to sign custom token. {0}'.format(error)
raise TokenSignError(msg, error)


def create_session_cookie(self, id_token, expires_in):
"""Creates a session cookie from the provided ID token."""
id_token = id_token.decode('utf-8') if isinstance(id_token, bytes) else id_token
Expand Down
77 changes: 77 additions & 0 deletions firebase_admin/appcheck.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Copyright 2021 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Firebase App Check module.
"""

try:
from google.firebase import appcheck_v1beta
existing = globals().keys()
for key, value in appcheck_v1beta.__dict__.items():
if not key.startswith('_') and key not in existing:
globals()[key] = value
except ImportError:
raise ImportError('Failed to import the Firebase App Check library for Python. Make sure '
'to install the "google-cloud-firestore" module.')

from firebase_admin import _token_gen
from firebase_admin import _utils


_FAC_ATTRIBUTE = '_appcheck'


def _get_fac_service(app=None):
return _utils.get_app_service(app, _FAC_ATTRIBUTE, _AppCheckClient.from_app)

def create_token(app_id, app=None):
project_id = _get_fac_service(app).project_id()
token = _get_fac_service(app).token_generator().create_custom_token_fac(app_id)
payload = {}
payload['app'] = 'projects/{project_number}/apps/{app_id}'.format(
project_number=project_id, app_id=app_id)
payload['custom_token'] = token
return _get_fac_service(app).get().exchange_custom_token(payload)


class _AppCheckClient:
"""Holds a Firebase App Check client instance."""

def __init__(self, credentials, project, token_generator):
self._project = project
self._client = appcheck_v1beta.services.token_exchange_service.TokenExchangeServiceClient(
credentials=credentials, transport='rest')
self._token_generator = token_generator

def get(self):
return self._client

def project_id(self):
return self._project

def token_generator(self):
return self._token_generator

@classmethod
def from_app(cls, app):
"""Creates a new _FirestoreClient for the specified app."""
credentials = app.credential.get_credential()
project = app.project_id
token_generator = _token_gen.TokenGenerator(app, http_client=None)
if not project:
raise ValueError(
'Project ID is required to access Firestore. Either set the projectId option, '
'or use service account credentials. Alternatively, set the GOOGLE_CLOUD_PROJECT '
'environment variable.')
return _AppCheckClient(credentials, project, token_generator)
119 changes: 119 additions & 0 deletions google/firebase/appcheck/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from google.firebase.appcheck_v1beta.services.config_service.client import ConfigServiceClient
from google.firebase.appcheck_v1beta.services.token_exchange_service.client import TokenExchangeServiceClient

from google.firebase.appcheck_v1beta.types.configuration import AppAttestConfig
from google.firebase.appcheck_v1beta.types.configuration import BatchGetAppAttestConfigsRequest
from google.firebase.appcheck_v1beta.types.configuration import BatchGetAppAttestConfigsResponse
from google.firebase.appcheck_v1beta.types.configuration import BatchGetDeviceCheckConfigsRequest
from google.firebase.appcheck_v1beta.types.configuration import BatchGetDeviceCheckConfigsResponse
from google.firebase.appcheck_v1beta.types.configuration import BatchGetRecaptchaConfigsRequest
from google.firebase.appcheck_v1beta.types.configuration import BatchGetRecaptchaConfigsResponse
from google.firebase.appcheck_v1beta.types.configuration import BatchGetSafetyNetConfigsRequest
from google.firebase.appcheck_v1beta.types.configuration import BatchGetSafetyNetConfigsResponse
from google.firebase.appcheck_v1beta.types.configuration import BatchUpdateServicesRequest
from google.firebase.appcheck_v1beta.types.configuration import BatchUpdateServicesResponse
from google.firebase.appcheck_v1beta.types.configuration import CreateDebugTokenRequest
from google.firebase.appcheck_v1beta.types.configuration import DebugToken
from google.firebase.appcheck_v1beta.types.configuration import DeleteDebugTokenRequest
from google.firebase.appcheck_v1beta.types.configuration import DeviceCheckConfig
from google.firebase.appcheck_v1beta.types.configuration import GetAppAttestConfigRequest
from google.firebase.appcheck_v1beta.types.configuration import GetDebugTokenRequest
from google.firebase.appcheck_v1beta.types.configuration import GetDeviceCheckConfigRequest
from google.firebase.appcheck_v1beta.types.configuration import GetRecaptchaConfigRequest
from google.firebase.appcheck_v1beta.types.configuration import GetSafetyNetConfigRequest
from google.firebase.appcheck_v1beta.types.configuration import GetServiceRequest
from google.firebase.appcheck_v1beta.types.configuration import ListDebugTokensRequest
from google.firebase.appcheck_v1beta.types.configuration import ListDebugTokensResponse
from google.firebase.appcheck_v1beta.types.configuration import ListServicesRequest
from google.firebase.appcheck_v1beta.types.configuration import ListServicesResponse
from google.firebase.appcheck_v1beta.types.configuration import RecaptchaConfig
from google.firebase.appcheck_v1beta.types.configuration import SafetyNetConfig
from google.firebase.appcheck_v1beta.types.configuration import Service
from google.firebase.appcheck_v1beta.types.configuration import UpdateAppAttestConfigRequest
from google.firebase.appcheck_v1beta.types.configuration import UpdateDebugTokenRequest
from google.firebase.appcheck_v1beta.types.configuration import UpdateDeviceCheckConfigRequest
from google.firebase.appcheck_v1beta.types.configuration import UpdateRecaptchaConfigRequest
from google.firebase.appcheck_v1beta.types.configuration import UpdateSafetyNetConfigRequest
from google.firebase.appcheck_v1beta.types.configuration import UpdateServiceRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import AppAttestChallengeResponse
from google.firebase.appcheck_v1beta.types.token_exchange_service import AttestationTokenResponse
from google.firebase.appcheck_v1beta.types.token_exchange_service import ExchangeAppAttestAssertionRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import ExchangeAppAttestAttestationRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import ExchangeAppAttestAttestationResponse
from google.firebase.appcheck_v1beta.types.token_exchange_service import ExchangeCustomTokenRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import ExchangeDebugTokenRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import ExchangeDeviceCheckTokenRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import ExchangeRecaptchaTokenRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import ExchangeSafetyNetTokenRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import GenerateAppAttestChallengeRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import GetPublicJwkSetRequest
from google.firebase.appcheck_v1beta.types.token_exchange_service import PublicJwk
from google.firebase.appcheck_v1beta.types.token_exchange_service import PublicJwkSet

__all__ = ('ConfigServiceClient',
'TokenExchangeServiceClient',
'AppAttestConfig',
'BatchGetAppAttestConfigsRequest',
'BatchGetAppAttestConfigsResponse',
'BatchGetDeviceCheckConfigsRequest',
'BatchGetDeviceCheckConfigsResponse',
'BatchGetRecaptchaConfigsRequest',
'BatchGetRecaptchaConfigsResponse',
'BatchGetSafetyNetConfigsRequest',
'BatchGetSafetyNetConfigsResponse',
'BatchUpdateServicesRequest',
'BatchUpdateServicesResponse',
'CreateDebugTokenRequest',
'DebugToken',
'DeleteDebugTokenRequest',
'DeviceCheckConfig',
'GetAppAttestConfigRequest',
'GetDebugTokenRequest',
'GetDeviceCheckConfigRequest',
'GetRecaptchaConfigRequest',
'GetSafetyNetConfigRequest',
'GetServiceRequest',
'ListDebugTokensRequest',
'ListDebugTokensResponse',
'ListServicesRequest',
'ListServicesResponse',
'RecaptchaConfig',
'SafetyNetConfig',
'Service',
'UpdateAppAttestConfigRequest',
'UpdateDebugTokenRequest',
'UpdateDeviceCheckConfigRequest',
'UpdateRecaptchaConfigRequest',
'UpdateSafetyNetConfigRequest',
'UpdateServiceRequest',
'AppAttestChallengeResponse',
'AttestationTokenResponse',
'ExchangeAppAttestAssertionRequest',
'ExchangeAppAttestAttestationRequest',
'ExchangeAppAttestAttestationResponse',
'ExchangeCustomTokenRequest',
'ExchangeDebugTokenRequest',
'ExchangeDeviceCheckTokenRequest',
'ExchangeRecaptchaTokenRequest',
'ExchangeSafetyNetTokenRequest',
'GenerateAppAttestChallengeRequest',
'GetPublicJwkSetRequest',
'PublicJwk',
'PublicJwkSet',
)
2 changes: 2 additions & 0 deletions google/firebase/appcheck/py.typed
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Marker file for PEP 561.
# The google-firebase-appcheck package uses inline types.
120 changes: 120 additions & 0 deletions google/firebase/appcheck_v1beta/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from .services.config_service import ConfigServiceClient
from .services.token_exchange_service import TokenExchangeServiceClient

from .types.configuration import AppAttestConfig
from .types.configuration import BatchGetAppAttestConfigsRequest
from .types.configuration import BatchGetAppAttestConfigsResponse
from .types.configuration import BatchGetDeviceCheckConfigsRequest
from .types.configuration import BatchGetDeviceCheckConfigsResponse
from .types.configuration import BatchGetRecaptchaConfigsRequest
from .types.configuration import BatchGetRecaptchaConfigsResponse
from .types.configuration import BatchGetSafetyNetConfigsRequest
from .types.configuration import BatchGetSafetyNetConfigsResponse
from .types.configuration import BatchUpdateServicesRequest
from .types.configuration import BatchUpdateServicesResponse
from .types.configuration import CreateDebugTokenRequest
from .types.configuration import DebugToken
from .types.configuration import DeleteDebugTokenRequest
from .types.configuration import DeviceCheckConfig
from .types.configuration import GetAppAttestConfigRequest
from .types.configuration import GetDebugTokenRequest
from .types.configuration import GetDeviceCheckConfigRequest
from .types.configuration import GetRecaptchaConfigRequest
from .types.configuration import GetSafetyNetConfigRequest
from .types.configuration import GetServiceRequest
from .types.configuration import ListDebugTokensRequest
from .types.configuration import ListDebugTokensResponse
from .types.configuration import ListServicesRequest
from .types.configuration import ListServicesResponse
from .types.configuration import RecaptchaConfig
from .types.configuration import SafetyNetConfig
from .types.configuration import Service
from .types.configuration import UpdateAppAttestConfigRequest
from .types.configuration import UpdateDebugTokenRequest
from .types.configuration import UpdateDeviceCheckConfigRequest
from .types.configuration import UpdateRecaptchaConfigRequest
from .types.configuration import UpdateSafetyNetConfigRequest
from .types.configuration import UpdateServiceRequest
from .types.token_exchange_service import AppAttestChallengeResponse
from .types.token_exchange_service import AttestationTokenResponse
from .types.token_exchange_service import ExchangeAppAttestAssertionRequest
from .types.token_exchange_service import ExchangeAppAttestAttestationRequest
from .types.token_exchange_service import ExchangeAppAttestAttestationResponse
from .types.token_exchange_service import ExchangeCustomTokenRequest
from .types.token_exchange_service import ExchangeDebugTokenRequest
from .types.token_exchange_service import ExchangeDeviceCheckTokenRequest
from .types.token_exchange_service import ExchangeRecaptchaTokenRequest
from .types.token_exchange_service import ExchangeSafetyNetTokenRequest
from .types.token_exchange_service import GenerateAppAttestChallengeRequest
from .types.token_exchange_service import GetPublicJwkSetRequest
from .types.token_exchange_service import PublicJwk
from .types.token_exchange_service import PublicJwkSet

__all__ = (
'AppAttestChallengeResponse',
'AppAttestConfig',
'AttestationTokenResponse',
'BatchGetAppAttestConfigsRequest',
'BatchGetAppAttestConfigsResponse',
'BatchGetDeviceCheckConfigsRequest',
'BatchGetDeviceCheckConfigsResponse',
'BatchGetRecaptchaConfigsRequest',
'BatchGetRecaptchaConfigsResponse',
'BatchGetSafetyNetConfigsRequest',
'BatchGetSafetyNetConfigsResponse',
'BatchUpdateServicesRequest',
'BatchUpdateServicesResponse',
'ConfigServiceClient',
'CreateDebugTokenRequest',
'DebugToken',
'DeleteDebugTokenRequest',
'DeviceCheckConfig',
'ExchangeAppAttestAssertionRequest',
'ExchangeAppAttestAttestationRequest',
'ExchangeAppAttestAttestationResponse',
'ExchangeCustomTokenRequest',
'ExchangeDebugTokenRequest',
'ExchangeDeviceCheckTokenRequest',
'ExchangeRecaptchaTokenRequest',
'ExchangeSafetyNetTokenRequest',
'GenerateAppAttestChallengeRequest',
'GetAppAttestConfigRequest',
'GetDebugTokenRequest',
'GetDeviceCheckConfigRequest',
'GetPublicJwkSetRequest',
'GetRecaptchaConfigRequest',
'GetSafetyNetConfigRequest',
'GetServiceRequest',
'ListDebugTokensRequest',
'ListDebugTokensResponse',
'ListServicesRequest',
'ListServicesResponse',
'PublicJwk',
'PublicJwkSet',
'RecaptchaConfig',
'SafetyNetConfig',
'Service',
'TokenExchangeServiceClient',
'UpdateAppAttestConfigRequest',
'UpdateDebugTokenRequest',
'UpdateDeviceCheckConfigRequest',
'UpdateRecaptchaConfigRequest',
'UpdateSafetyNetConfigRequest',
'UpdateServiceRequest',
)
Loading