Skip to content

Commit

Permalink
feat(api): add intercom user hash to auth response (#664)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucianHymer authored Aug 22, 2024
1 parent a492689 commit 5a426f0
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 6 deletions.
2 changes: 2 additions & 0 deletions api/ceramic_cache/api/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Any, Dict, List, Optional

from ninja_schema import Schema

from registry.api.v1 import DetailedScoreResponse

from ..models import CeramicCache
Expand Down Expand Up @@ -46,6 +47,7 @@ class CacaoVerifySubmit(Schema):

class AccessTokenResponse(Schema):
access: str
intercom_user_hash: str


class ComposeDBStatusPayload(Schema):
Expand Down
24 changes: 19 additions & 5 deletions api/ceramic_cache/api/v1.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Ceramic Cache API"""

import hashlib
import hmac
import json
from datetime import timedelta
from typing import Any, Dict, List, Optional, Type
Expand Down Expand Up @@ -543,6 +545,22 @@ def authenticate(request, payload: CacaoVerifySubmit):
return handle_authenticate(payload)


def generate_access_token_response(user_did: str) -> AccessTokenResponse:
token = DbCacheToken()
token["did"] = user_did

intercom_user_hash = hmac.new(
bytes(settings.INTERCOM_SECRET_KEY, encoding="utf-8"),
bytes(user_did, encoding="utf-8"),
digestmod=hashlib.sha256,
).hexdigest()

return AccessTokenResponse(
access=str(token.access_token),
intercom_user_hash=intercom_user_hash,
)


def handle_authenticate(payload: CacaoVerifySubmit) -> AccessTokenResponse:
# First validate the payload
# This will ensure that the payload signature was made for our unique nonce
Expand Down Expand Up @@ -573,11 +591,7 @@ def handle_authenticate(payload: CacaoVerifySubmit) -> AccessTokenResponse:
if res.status_code == 200:
data = res.json()
if data.get("status") == "ok":
token = DbCacheToken()
token["did"] = payload.issuer
return {
"access": str(token.access_token),
}
return generate_access_token_response(payload.issuer)

log.error(
"Failed to validate authentication payload (jws)! Response: %s\n%s",
Expand Down
14 changes: 13 additions & 1 deletion api/ceramic_cache/test/test_authenticate_v1.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import copy
import hashlib
import hmac
import json
from collections import namedtuple

import pytest
from django.conf import settings
from django.test import Client
from ninja_jwt.tokens import AccessToken

Expand Down Expand Up @@ -70,10 +72,20 @@ def json(self):

assert auth_response.status_code == 200
assert "access" in json_data
assert "intercom_user_hash" in json_data

token = AccessToken(json_data["access"])
assert token["did"] == payload["issuer"]

assert (
json_data["intercom_user_hash"]
== hmac.new(
bytes(settings.INTERCOM_SECRET_KEY, encoding="utf-8"),
bytes(payload["issuer"], encoding="utf-8"),
digestmod=hashlib.sha256,
).hexdigest()
)

def test_authenticate_fails_to_validate_invalid_payload(self, mocker):
"""
We expect that the authenticate request:
Expand Down
1 change: 1 addition & 0 deletions api/scorer/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env("SECRET_KEY")
INTERCOM_SECRET_KEY = env("INTERCOM_SECRET_KEY", default="TEST123")

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env("DEBUG", default=True)
Expand Down

0 comments on commit 5a426f0

Please sign in to comment.