Skip to content

Commit 1f59841

Browse files
committed
Add DS_Store to ignore, fix logging for SMS
1 parent 7749e30 commit 1f59841

File tree

5 files changed

+44
-33
lines changed

5 files changed

+44
-33
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,6 @@ venv.bak/
106106

107107
# defualt config
108108
config-local.json
109+
110+
# MacOS
111+
*.DS_Store

configschema.json

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,16 @@
126126
"default": "Tapis Token Webapp"
127127
},
128128
"turn_off_mfa": {
129-
"type": "boolean",
130-
"description": "A single configuration that will cause Authenticator to disable all MFA checks.",
131-
"default": false
132-
}
129+
"type": "boolean",
130+
"description": "A single configuration that will cause Authenticator to disable all MFA checks.",
131+
"default": false
133132
},
134-
"required": ["dev_ldap_tenant_id"]
133+
"privacy_idea_jwt": {
134+
"type": "string",
135+
"description": "The Tapis service token to authenticate to Privacy Idea."
136+
}
137+
},
138+
"required": [
139+
"dev_ldap_tenant_id"
140+
]
135141
}

service/mfa.py

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,16 @@ def check_sms(tenant_id, username):
5252
config_data = get_config_data(mfa_config)
5353

5454
if config_data:
55-
if 'privacy_idea_jwt' in config_data:
56-
jwt = config_data['privacy_idea_jwt']
57-
else:
58-
jwt = get_privacy_idea_jwt(config_data['privacy_idea_url'], config_data['privacy_idea_client_id'], config_data['privacy_idea_client_key'])
55+
jwt = conf.privacy_idea_jwt if conf.privacy_idea_jwt else get_privacy_idea_jwt(config_data['privacy_idea_url'], config_data['privacy_idea_client_id'], config_data['privacy_idea_client_key'])
5956
headers = {"Authorization": jwt}
57+
logger.debug(headers)
6058
data = {"serial": username}
6159
res = requests.get(f"{config_data['privacy_idea_url']}/token?serial={username}", headers=headers, data=data)
6260
result = res.json()["result"]
63-
logger.debug(f"REQUEST RESULT: {result}")
61+
logger.debug(f"Serial request from Privacy Idea for {username}: {result}")
6462
return res.json()["result"]["value"]["tokens"][0]["tokentype"] == "sms"
6563
except Exception as e:
66-
logger.debug(e)
64+
logger.debug(f"Error checking SMS for {username}: {e}")
6765

6866
return False
6967

@@ -77,13 +75,14 @@ def send_sms(tenant_id, username):
7775
config_data = get_config_data(mfa_config)
7876

7977
if config_data:
80-
jwt = config_data['privacy_idea_jwt']
78+
jwt = conf.privacy_idea_jwt
8179
headers = {"Authorization": jwt}
80+
logger.debug(headers)
8281
data = {"serial": username}
8382
res = requests.post(f"{config_data['privacy_idea_url']}/validate/triggerchallenge", headers=headers, data=data)
8483
return res.status_code == 200
8584
except Exception as e:
86-
logger.debug(e)
85+
logger.debug(f"Error sending SMS to {username}: {e}")
8786

8887

8988
def call_mfa(token, tenant_id, username):
@@ -99,10 +98,7 @@ def call_mfa(token, tenant_id, username):
9998

10099
if "tacc" in mfa_config:
101100
config = get_config_data(mfa_config)
102-
if 'privacy_idea_jwt' in config:
103-
jwt = config['privacy_idea_jwt']
104-
else:
105-
jwt = get_privacy_idea_jwt(config['privacy_idea_url'], config['privacy_idea_client_id'], config['privacy_idea_client_key'])
101+
jwt = conf.privacy_idea_jwt if conf.privacy_idea_jwt else get_privacy_idea_jwt(config['privacy_idea_url'], config['privacy_idea_client_id'], config['privacy_idea_client_key'])
106102
return verify_mfa_token(config['privacy_idea_url'], jwt, token, username, config['realm'])
107103

108104

@@ -111,21 +107,12 @@ def get_config_data(config):
111107
data['privacy_idea_url'] = config['tacc']['privacy_idea_url']
112108
data['privacy_idea_client_id'] = config['tacc']['privacy_idea_client_id']
113109
data['privacy_idea_client_key'] = config['tacc']['privacy_idea_client_key']
114-
data['privacy_idea_jwt'] = config['tacc'].get('privacy_idea_jwt', None)
115110
data['grant_types'] = config['tacc'].get('grant_types', '')
116111
data['realm'] = config['tacc'].get('realm', 'tacc')
117112

118113
return data
119114

120115

121-
def privacy_idea_tacc(config, token, username):
122-
jwt = get_privacy_idea_jwt(config['privacy_idea_url'], config['privacy_idea_client_id'], config['privacy_idea_client_key'])
123-
if not jwt:
124-
return False
125-
126-
return verify_mfa_token(config['privacy_idea_url'], config['privacy_idea_jwt'], token, username, config['realm'])
127-
128-
129116
def get_privacy_idea_jwt(url, username, password):
130117
data = {
131118
"username": username,

service/templates/login.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ <h1>
1515
<span>Log In</span>
1616
</h1>
1717
<p>to continue to the <var>{{ client_display_name }}</var></p>
18+
{% if client_display_name == 'DesignSafe JupyterHub' %}
19+
<p>Warning: Files saved in the top most directory will be wiped on server restart. Please save files to MyData or to a Project.</p>
20+
{% endif %}
1821

1922
{% if error %}
2023
<ul>

service/tests/basic_test.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,17 @@ def check_device_code_table(client_id, user_code, device_code, verification_url,
194194
retrieved = models.DeviceCode.query.filter_by(user_code=user_code).first()
195195
print(f'DEBUG: got device code object:: {retrieved}')
196196
if negative:
197-
assert retrieved == None
197+
assert retrieved is None
198198
return
199199
assert retrieved.code == device_code
200200
assert retrieved.user_code == user_code
201201
assert retrieved.tenant_id == TEST_TENANT_ID
202202
assert retrieved.client_id == client_id
203-
assert retrieved.client_key == TEST_CLIENT_KEY
203+
assert retrieved.client_key == TEST_CLIENT_KEY
204204
assert retrieved.status == status
205205
assert retrieved.verification_uri == verification_url
206206

207+
207208
def validate_refresh_token(response):
208209
"""
209210
Validate that a response has a refresh token and it is properly formatted.
@@ -221,6 +222,7 @@ def validate_refresh_token(response):
221222
assert claims['tapis/access_token']['sub'] == f'{TEST_USERNAME}@{TEST_TENANT_ID}'
222223
return claims
223224

225+
224226
def get_jwt(client):
225227
# TODO: add assertions for failing to get a token -- this should fail the current test somehow
226228
# auth_header = {'Authorization': get_basic_auth_header(TEST_CLIENT_ID, TEST_CLIENT_KEY)}
@@ -241,17 +243,20 @@ def get_jwt(client):
241243
access_token_str = response.json['result']['access_token']['access_token']
242244
return access_token_str
243245

246+
244247
def gen_mfa_token(username, tokencode=None):
245248
"""
246249
Generate a OTP mfa code using pyotp given a username and token code.
247250
If a token code is not provided, a random one will be used.
248251
"""
249252
pass
250253

254+
251255
# =====================
252256
# Actual test functions
253257
# =====================
254258

259+
255260
## utility tests
256261
# get jwt
257262
def test_get_jwt(client):
@@ -262,6 +267,7 @@ def test_get_jwt(client):
262267
result = get_jwt(client)
263268
print(f'got result = {result}')
264269

270+
265271
# get mfa config
266272
def test_get_mfa_config(client):
267273
print('top of get mfa config')
@@ -289,6 +295,7 @@ def test_get_mfa_config(client):
289295
print(f'got {e} while trying to get mfa config for tenant {TEST_TENANT_ID}')
290296
raise Exception()
291297

298+
292299
## Health Check
293300
# hello
294301
def test_authenticator_hello(client):
@@ -301,23 +308,27 @@ def test_authenticator_ready(client):
301308
result = client.get('http://localhost:5000/v3/oauth2/ready')
302309
assert result.status_code == 200
303310

311+
304312
## Metadata
305313
# get_server_metadata
306314
def test_get_metadata(client):
307315
result = client.get("http://localhost:5000/v3/oauth2/.well-known/oauth-authorization-server")
308316
assert result.status_code == 200
309317

318+
310319
## Admin
311320
# get_config
312321
# update_config
313322

314323
## Clients
315324

325+
316326
def test_invalid_post(client):
317327
with client:
318328
response = client.post("http://localhost:5000/v3/oauth2/clients")
319329
assert response.status_code == 400
320330

331+
321332
# list_clients
322333
def test_authenticator_list_clients(client, capsys):
323334
# result = client.authenticator.list_clients()
@@ -326,6 +337,7 @@ def test_authenticator_list_clients(client, capsys):
326337
result = client.get('http://localhost:5000/v3/oauth2/clients', headers=header)
327338
assert result.status_code == 200
328339

340+
329341
# create_client
330342
def test_authenticator_create_clients(client, capsys): ## TODO: this works, but doing it twice violates uniqueness constraint. Need to find a way to reliably erase it without using another endpoint
331343
# result = client.authenticator.create_client(client_id=TEST_CLIENT_ID, callback_url='https://foo.example.com/oauth2/callback')
@@ -522,7 +534,7 @@ def test_password_grant_no_client(client, init_db):
522534
assert 'access_token' in response.json['result']
523535
# validate access_token:
524536
claims = validate_access_token(response)
525-
assert claims['tapis/client_id'] == None
537+
assert claims['tapis/client_id'] is None
526538
assert claims['tapis/grant_type'] == 'password'
527539
# when not using an oauth client, refresh tokens are not returned:
528540
assert 'refresh_token' not in response.json['result']
@@ -565,7 +577,7 @@ def test_revoke_token(client, init_db):
565577
data=json.dumps(payload),
566578
content_type='application/json'
567579
)
568-
assert response.status_code == 200
580+
assert response.status_code == 200
569581
check_access_token_table(access_token_claims, "password", True, TEST_CLIENT_ID)
570582

571583
# then the refresh token
@@ -575,7 +587,7 @@ def test_revoke_token(client, init_db):
575587
data=json.dumps(payload),
576588
content_type='application/json'
577589
)
578-
assert response.status_code == 200
590+
assert response.status_code == 200
579591

580592
check_refresh_token_table(refresh_token_claims, "password", True, TEST_CLIENT_ID)
581593

@@ -799,12 +811,12 @@ def test_exchange_device_code(client):
799811
access_token_ttl=models.DeviceCode.set_ttl())
800812
except Exception as e:
801813
print(f'ERROR: exception while generating device code object:: {e}')
802-
assert device_code != None
814+
assert device_code is not None
803815
print(f'DEBUG: have device code object: {device_code}')
804816
try:
805817
models.db.session.add(device_code)
806818
models.db.session.commit()
807-
print(f'DEBUG: committed device code object to DB')
819+
print('DEBUG: committed device code object to DB')
808820
except Exception as e:
809821
print(f"Got exception trying to add and commit the device code. e: {e}; type(e): {type(e)}")
810822
raise Exception("Internal error saving device code. Please try again later.")

0 commit comments

Comments
 (0)