Skip to content

Commit ea2befc

Browse files
authored
Merge pull request #15 from y-temp4/update-token-api
ALIS-3524: Check phone_number_verified when post /token API
2 parents 6c43612 + ba4275d commit ea2befc

File tree

6 files changed

+84
-6
lines changed

6 files changed

+84
-6
lines changed

.envrc.sample

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ export PYTHONPATH=./ # 変更必要なし
66
export ALIS_APP_ID=xxxxxxxx # serverless-applicationで指定した値を指定してください。environmentsリポジトリのsecretパラメータを判定するのに必要です
77
export TEST_COGNITO_USER_POOL_ID=xxxxx # インテグレーションテストで使用されるCognito User Pool IDを指定してください
88
export TEST_COGNITO_CLIENT_ID=xxxxx # インテグレーションテストで使用されるCognito User Pool へアクセスできるアプリクライアントのIDを指定してください。このアプリはADMIN_NO_SRP_AUTHをサポートしている必要があります
9-
export TEST_COGNITO_USER_ID=xxxxx # インテグレーションテストで使用されるCognitoのUserIDを指定してください。environmentリポジトリで指定しているUserpoolにそのユーザが存在している必要があります
9+
export TEST_COGNITO_USER_ID=xxxxx # インテグレーションテストで使用されるCognitoのUserIDを指定してください。environmentリポジトリで指定しているUserpoolにそのユーザが存在している必要があります。また、このユーザーはphone_number_verifiedをtrueの状態にしてください。
10+
export TEST_COGNITO_PHONE_NUMBER_NOT_VERIFIED_USER_ID=xxxxx # TEST_COGNITO_USER_IDと同様なユーザー。ただし、このユーザーはphone_number_verifiedをfalseの状態にしてください。
1011
export TEST_AUTHLETE_SERVER_APP_CLIENT_ID=xxxxx # インテグレーションテストで使用するサーバーサイドアプリケーションのAuthleteのclient_idを指定してください
1112
export TEST_AUTHLETE_SERVER_APP_CLIENT_SECRET=xxxxx # インテグレーションテストで使用するサーバーサイドアプリケーションのAuthleteのclient_secretを指定してください
1213
export TEST_AUTHLETE_CLIENT_APP_CLIENT_ID=xxxxx # インテグレーションテストで使用するクライアントアプリケーションのAuthleteのclient_idを指定してください

lambdas/http/token.py

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import os
22
from lib.authlete_sdk import AuthleteSdk
33
from lib.exceptions import ValidationError, AuthleteApiError
4+
from lib.cognito_user_pool import CognitoUserPool
45
from lib.utils import response_builder, logger, verify_supported_media_type
56

67

78
def handler(event, context):
9+
# 初期化処理
10+
token = {}
11+
authlete = None
812
try:
9-
logger.info(event)
1013
if verify_supported_media_type(event['headers']) is False:
1114
return response_builder(415, {
1215
'error_message': "This API only support 'content-type: application/x-www-form-urlencoded' media type"
@@ -16,7 +19,14 @@ def handler(event, context):
1619
api_key=os.environ['AUTHLETE_API_KEY'],
1720
api_secret=os.environ['AUTHLETE_API_SECRET']
1821
)
22+
except Exception as e:
23+
logger.error(e)
24+
return response_builder(500, {
25+
'error_message': 'Internal Server Error'
26+
})
1927

28+
# トークン取得処理
29+
try:
2030
grant_type = authlete.get_grant_type(
2131
body=event['body']
2232
)
@@ -38,7 +48,6 @@ def handler(event, context):
3848
client_id=data['client_id'],
3949
client_secret=data['client_secret']
4050
)
41-
return response_builder(200, token)
4251
elif grant_type == 'refresh_token':
4352
if data.get('client_secret') is None:
4453
token = authlete.get_access_token_from_refresh_token(
@@ -51,7 +60,6 @@ def handler(event, context):
5160
client_id=data['client_id'],
5261
client_secret=data['client_secret']
5362
)
54-
return response_builder(200, token)
5563
else:
5664
return response_builder(400, {
5765
'error_message': 'invalid grant_type'
@@ -70,3 +78,30 @@ def handler(event, context):
7078
return response_builder(500, {
7179
'error_message': 'Internal Server Error'
7280
})
81+
82+
try:
83+
congito_user_pool = CognitoUserPool(
84+
user_pool_id=os.environ['COGNITO_USER_POOL_ID']
85+
)
86+
87+
access_token = token.get('access_token')
88+
response_content = authlete.get_user_info(access_token=access_token)
89+
attributes = congito_user_pool.get_user_attributes(username=response_content['sub'])
90+
phone_number_verified = 'false'
91+
92+
for attribute in attributes:
93+
if attribute['Name'] == 'phone_number_verified':
94+
phone_number_verified = attribute['Value']
95+
96+
if phone_number_verified == 'true':
97+
return response_builder(200, token)
98+
else:
99+
return response_builder(403, {
100+
'error_message': 'phone_number must be verified'
101+
})
102+
103+
except Exception as e:
104+
logger.error(e)
105+
return response_builder(500, {
106+
'error_message': 'Internal Server Error'
107+
})

lib/cognito_user_pool.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,14 @@ def get_user_sub_value(self, username):
1818

1919
except ClientError as e:
2020
raise e
21+
22+
def get_user_attributes(self, username):
23+
try:
24+
response = self.client.admin_get_user(
25+
UserPoolId=self.user_pool_id,
26+
Username=username
27+
)
28+
return response['UserAttributes']
29+
30+
except ClientError as e:
31+
raise e

tests/integration/common.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def get_refresh_token(self, code_verifier, code_challenge):
9797
data = response.json()
9898
return data['refreshToken']
9999

100-
def get_authorization_code(self, code_challenge):
100+
def get_authorization_code(self, code_challenge, is_phone_number_verified_user=True):
101101
response = requests.post(
102102
url='https://api.authlete.com/api/auth/authorization',
103103
auth=(
@@ -109,14 +109,16 @@ def get_authorization_code(self, code_challenge):
109109
)
110110
data = response.json()
111111

112+
cognito_user_id = os.environ['TEST_COGNITO_USER_ID'] if is_phone_number_verified_user else os.environ['TEST_COGNITO_PHONE_NUMBER_NOT_VERIFIED_USER_ID']
113+
112114
response = requests.post(
113115
url='https://api.authlete.com/api/auth/authorization/issue',
114116
auth=(
115117
self.authlete_api_key,
116118
self.authlete_api_secret
117119
),
118120
headers={'content-type': 'application/json'},
119-
data=json.dumps({'ticket': data['ticket'], 'subject': os.environ['TEST_COGNITO_USER_ID']})
121+
data=json.dumps({'ticket': data['ticket'], 'subject': cognito_user_id})
120122
)
121123

122124
data = response.json()

tests/integration/test_token_client_app.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def setup(self):
1212
self.code_verifier = authlete_test_sdk.get_code_verifier()
1313
self.code_challenge = authlete_test_sdk.get_code_challenge(self.code_verifier)
1414
self.authorization_code = authlete_test_sdk.get_authorization_code(self.code_challenge)
15+
self.authorization_code_by_phone_number_not_verified_user = authlete_test_sdk.get_authorization_code(self.code_challenge, False)
1516

1617
def test_return_200_with_authorization_code(self, endpoint):
1718
response = requests.post(
@@ -133,3 +134,16 @@ def test_return_400_with_missing_client_id(self, endpoint):
133134
assert response.status_code == 400
134135
error = response.json()
135136
assert error['error_message'] == 'Missing client_id'
137+
138+
def test_return_403_with_phone_number_not_verified_user(self, endpoint):
139+
response = requests.post(
140+
url=endpoint + '/token',
141+
headers={
142+
'Content-Type': 'application/x-www-form-urlencoded'
143+
},
144+
data='grant_type=authorization_code&code='+self.authorization_code_by_phone_number_not_verified_user+'&redirect_uri=http://localhost&code_verifier='+self.code_verifier+'&client_id='+os.environ['TEST_AUTHLETE_CLIENT_APP_CLIENT_ID']
145+
)
146+
147+
assert response.status_code == 403
148+
error = response.json()
149+
assert error['error_message'] == 'phone_number must be verified'

tests/integration/test_token_server_app.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ def setup(self):
1313
self.code_verifier = authlete_test_sdk.get_code_verifier()
1414
self.code_challenge = authlete_test_sdk.get_code_challenge(self.code_verifier)
1515
self.authorization_code = authlete_test_sdk.get_authorization_code(self.code_challenge)
16+
self.authorization_code_by_phone_number_not_verified_user = authlete_test_sdk.get_authorization_code(self.code_challenge, False)
1617

1718
def test_return_200_with_authorization_code(self, endpoint):
1819
response = requests.post(
@@ -158,3 +159,17 @@ def test_return_400_with_invalid_client_secret(self, endpoint):
158159
assert response.status_code == 400
159160
error = response.json()
160161
assert error['error_message'] == 'The client credentials contained in the token request are invalid.'
162+
163+
def test_return_403_with_phone_number_not_verified_user(self, endpoint):
164+
response = requests.post(
165+
url=endpoint + '/token',
166+
headers={
167+
'Content-Type': 'application/x-www-form-urlencoded',
168+
'Authorization': 'Basic '+authlete_test_sdk.get_token_for_client_authentication()
169+
},
170+
data='grant_type=authorization_code&code='+self.authorization_code_by_phone_number_not_verified_user+'&redirect_uri=http://localhost&code_verifier='+self.code_verifier
171+
)
172+
173+
assert response.status_code == 403
174+
error = response.json()
175+
assert error['error_message'] == 'phone_number must be verified'

0 commit comments

Comments
 (0)