Merge pull request #291 from dod-ccpo/logout-#159903121
Logout #159903121
This commit is contained in:
commit
fbdf8b0ee6
@ -49,10 +49,9 @@ def login_redirect():
|
|||||||
return redirect(url_for(".home"))
|
return redirect(url_for(".home"))
|
||||||
|
|
||||||
|
|
||||||
def _is_valid_certificate(request):
|
@bp.route("/logout")
|
||||||
cert = request.environ.get("HTTP_X_SSL_CLIENT_CERT")
|
def logout():
|
||||||
if cert:
|
if session.get("user_id"):
|
||||||
result = app.crl_validator.validate(cert.encode())
|
del (session["user_id"])
|
||||||
return result
|
|
||||||
else:
|
return redirect(url_for(".home"))
|
||||||
return False
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
{{ Icon('avatar', classes='topbar__link-icon') }}
|
{{ Icon('avatar', classes='topbar__link-icon') }}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="/" class="topbar__link" title='Log out of JEDI Cloud'>
|
<a href="{{ url_for('atst.logout') }}" class="topbar__link" title='Log out of JEDI Cloud'>
|
||||||
{{ Icon('logout', classes='topbar__link-icon') }}
|
{{ Icon('logout', classes='topbar__link-icon') }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from flask import session, url_for
|
from flask import session, url_for
|
||||||
from .mocks import DOD_SDN_INFO, DOD_SDN, FIXTURE_EMAIL_ADDRESS
|
from .mocks import DOD_SDN_INFO, DOD_SDN, FIXTURE_EMAIL_ADDRESS
|
||||||
@ -14,6 +16,17 @@ def _fetch_user_info(c, t):
|
|||||||
return MOCK_USER
|
return MOCK_USER
|
||||||
|
|
||||||
|
|
||||||
|
def _login(client, verify="SUCCESS", sdn=DOD_SDN, cert=""):
|
||||||
|
return client.get(
|
||||||
|
url_for("atst.login_redirect"),
|
||||||
|
environ_base={
|
||||||
|
"HTTP_X_SSL_CLIENT_VERIFY": verify,
|
||||||
|
"HTTP_X_SSL_CLIENT_S_DN": sdn,
|
||||||
|
"HTTP_X_SSL_CLIENT_CERT": cert,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_successful_login_redirect_non_ccpo(client, monkeypatch):
|
def test_successful_login_redirect_non_ccpo(client, monkeypatch):
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"atst.domain.authnid.AuthenticationContext.authenticate", lambda *args: True
|
"atst.domain.authnid.AuthenticationContext.authenticate", lambda *args: True
|
||||||
@ -23,14 +36,7 @@ def test_successful_login_redirect_non_ccpo(client, monkeypatch):
|
|||||||
lambda *args: UserFactory.create(),
|
lambda *args: UserFactory.create(),
|
||||||
)
|
)
|
||||||
|
|
||||||
resp = client.get(
|
resp = _login(client)
|
||||||
"/login-redirect",
|
|
||||||
environ_base={
|
|
||||||
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
|
||||||
"HTTP_X_SSL_CLIENT_S_DN": "",
|
|
||||||
"HTTP_X_SSL_CLIENT_CERT": "",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
assert resp.status_code == 302
|
assert resp.status_code == 302
|
||||||
assert "home" in resp.headers["Location"]
|
assert "home" in resp.headers["Location"]
|
||||||
@ -47,14 +53,7 @@ def test_successful_login_redirect_ccpo(client, monkeypatch):
|
|||||||
lambda *args: UserFactory.create(atat_role=role),
|
lambda *args: UserFactory.create(atat_role=role),
|
||||||
)
|
)
|
||||||
|
|
||||||
resp = client.get(
|
resp = _login(client)
|
||||||
"/login-redirect",
|
|
||||||
environ_base={
|
|
||||||
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
|
||||||
"HTTP_X_SSL_CLIENT_S_DN": "",
|
|
||||||
"HTTP_X_SSL_CLIENT_CERT": "",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
assert resp.status_code == 302
|
assert resp.status_code == 302
|
||||||
assert "home" in resp.headers["Location"]
|
assert "home" in resp.headers["Location"]
|
||||||
@ -62,7 +61,7 @@ def test_successful_login_redirect_ccpo(client, monkeypatch):
|
|||||||
|
|
||||||
|
|
||||||
def test_unsuccessful_login_redirect(client, monkeypatch):
|
def test_unsuccessful_login_redirect(client, monkeypatch):
|
||||||
resp = client.get("/login-redirect")
|
resp = client.get(url_for("atst.login_redirect"))
|
||||||
|
|
||||||
assert resp.status_code == 401
|
assert resp.status_code == 401
|
||||||
assert "user_id" not in session
|
assert "user_id" not in session
|
||||||
@ -99,26 +98,12 @@ def test_crl_validation_on_login(client):
|
|||||||
bad_cert = open("ssl/client-certs/bad-atat.mil.crt").read()
|
bad_cert = open("ssl/client-certs/bad-atat.mil.crt").read()
|
||||||
|
|
||||||
# bad cert is on the test CRL
|
# bad cert is on the test CRL
|
||||||
resp = client.get(
|
resp = _login(client, cert=bad_cert)
|
||||||
"/login-redirect",
|
|
||||||
environ_base={
|
|
||||||
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
|
||||||
"HTTP_X_SSL_CLIENT_S_DN": DOD_SDN,
|
|
||||||
"HTTP_X_SSL_CLIENT_CERT": bad_cert,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
assert resp.status_code == 401
|
assert resp.status_code == 401
|
||||||
assert "user_id" not in session
|
assert "user_id" not in session
|
||||||
|
|
||||||
# good cert is not on the test CRL, passes
|
# good cert is not on the test CRL, passes
|
||||||
resp = client.get(
|
resp = _login(client, cert=good_cert)
|
||||||
"/login-redirect",
|
|
||||||
environ_base={
|
|
||||||
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
|
||||||
"HTTP_X_SSL_CLIENT_S_DN": DOD_SDN,
|
|
||||||
"HTTP_X_SSL_CLIENT_CERT": good_cert,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
assert session["user_id"]
|
assert session["user_id"]
|
||||||
|
|
||||||
|
|
||||||
@ -132,14 +117,7 @@ def test_creates_new_user_on_login(monkeypatch, client):
|
|||||||
with pytest.raises(NotFoundError):
|
with pytest.raises(NotFoundError):
|
||||||
Users.get_by_dod_id(DOD_SDN_INFO["dod_id"])
|
Users.get_by_dod_id(DOD_SDN_INFO["dod_id"])
|
||||||
|
|
||||||
resp = client.get(
|
resp = _login(client, cert=cert_file)
|
||||||
"/login-redirect",
|
|
||||||
environ_base={
|
|
||||||
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
|
||||||
"HTTP_X_SSL_CLIENT_S_DN": DOD_SDN,
|
|
||||||
"HTTP_X_SSL_CLIENT_CERT": cert_file,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
user = Users.get_by_dod_id(DOD_SDN_INFO["dod_id"])
|
user = Users.get_by_dod_id(DOD_SDN_INFO["dod_id"])
|
||||||
assert user.first_name == DOD_SDN_INFO["first_name"]
|
assert user.first_name == DOD_SDN_INFO["first_name"]
|
||||||
@ -148,23 +126,36 @@ def test_creates_new_user_on_login(monkeypatch, client):
|
|||||||
|
|
||||||
|
|
||||||
def test_creates_new_user_without_email_on_login(monkeypatch, client):
|
def test_creates_new_user_without_email_on_login(monkeypatch, client):
|
||||||
monkeypatch.setattr("atst.routes._is_valid_certificate", lambda *args: True)
|
|
||||||
cert_file = open("ssl/client-certs/atat.mil.crt").read()
|
cert_file = open("ssl/client-certs/atat.mil.crt").read()
|
||||||
|
|
||||||
# ensure user does not exist
|
# ensure user does not exist
|
||||||
with pytest.raises(NotFoundError):
|
with pytest.raises(NotFoundError):
|
||||||
Users.get_by_dod_id(DOD_SDN_INFO["dod_id"])
|
Users.get_by_dod_id(DOD_SDN_INFO["dod_id"])
|
||||||
|
|
||||||
resp = client.get(
|
resp = _login(client, cert=cert_file)
|
||||||
"/login-redirect",
|
|
||||||
environ_base={
|
|
||||||
"HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS",
|
|
||||||
"HTTP_X_SSL_CLIENT_S_DN": DOD_SDN,
|
|
||||||
"HTTP_X_SSL_CLIENT_CERT": cert_file,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
user = Users.get_by_dod_id(DOD_SDN_INFO["dod_id"])
|
user = Users.get_by_dod_id(DOD_SDN_INFO["dod_id"])
|
||||||
assert user.first_name == DOD_SDN_INFO["first_name"]
|
assert user.first_name == DOD_SDN_INFO["first_name"]
|
||||||
assert user.last_name == DOD_SDN_INFO["last_name"]
|
assert user.last_name == DOD_SDN_INFO["last_name"]
|
||||||
assert user.email == None
|
assert user.email == None
|
||||||
|
|
||||||
|
|
||||||
|
def test_logout(app, client, monkeypatch):
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"atst.domain.authnid.AuthenticationContext.authenticate", lambda s: True
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"atst.domain.authnid.AuthenticationContext.get_user",
|
||||||
|
lambda s: UserFactory.create(),
|
||||||
|
)
|
||||||
|
# create a real session
|
||||||
|
resp = _login(client)
|
||||||
|
resp_success = client.get(url_for("requests.requests_index"))
|
||||||
|
# verify session is valid
|
||||||
|
assert resp_success.status_code == 200
|
||||||
|
client.get(url_for("atst.logout"))
|
||||||
|
resp_failure = client.get(url_for("requests.requests_index"))
|
||||||
|
# verify that logging out has cleared the session
|
||||||
|
assert resp_failure.status_code == 302
|
||||||
|
destination = urlparse(resp_failure.headers["Location"]).path
|
||||||
|
assert destination == url_for("atst.root")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user