-
-
Notifications
You must be signed in to change notification settings - Fork 923
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Jens Langhammer <[email protected]>
- Loading branch information
Showing
14 changed files
with
1,340 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
authentik/stages/authenticator_endpoint/migrations/0001_initial.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,29 @@ | ||
from django.http import HttpResponse | ||
from django.urls import reverse | ||
|
||
from authentik.flows.challenge import ( | ||
Challenge, | ||
ChallengeResponse, | ||
FrameChallenge, | ||
FrameChallengeResponse, | ||
) | ||
from authentik.flows.stage import ChallengeStageView | ||
|
||
|
||
class AuthenticatorEndpointStageView(ChallengeStageView): | ||
"""Endpoint stage""" | ||
|
||
response_class = FrameChallengeResponse | ||
|
||
def get_challenge(self, *args, **kwargs) -> Challenge: | ||
return FrameChallenge( | ||
data={ | ||
"component": "xak-flow-frame", | ||
"url": self.request.build_absolute_uri( | ||
reverse("authentik_stages_authenticator_endpoint:chrome") | ||
), | ||
} | ||
) | ||
|
||
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: | ||
return self.executor.stage_ok() | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
66 changes: 66 additions & 0 deletions
66
authentik/stages/authenticator_endpoint/views/google_chrome/dtc.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
from json import dumps, loads | ||
from typing import Any | ||
|
||
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect | ||
from django.urls import reverse | ||
from django.views import View | ||
from google.oauth2.service_account import Credentials | ||
from googleapiclient.discovery import build | ||
|
||
from authentik.flows.planner import FlowPlan | ||
from authentik.flows.views.executor import SESSION_KEY_PLAN | ||
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS | ||
|
||
# Header we get from chrome that initiates verified access | ||
HEADER_DEVICE_TRUST = "X-Device-Trust" | ||
# Header we send to the client with the challenge | ||
HEADER_ACCESS_CHALLENGE = "X-Verified-Access-Challenge" | ||
# Header we get back from the client that we verify with google | ||
HEADER_ACCESS_CHALLENGE_RESPONSE = "X-Verified-Access-Challenge-Response" | ||
# Header value for x-device-trust that initiates the flow | ||
DEVICE_TRUST_VERIFIED_ACCESS = "VerifiedAccess" | ||
|
||
|
||
class GoogleChromeDeviceTrustConnector(View): | ||
|
||
def setup(self, request: HttpRequest, *args: Any, **kwargs: Any) -> None: | ||
self.google_client = build( | ||
"verifiedaccess", | ||
"v2", | ||
cache_discovery=False, | ||
credentials=Credentials.from_service_account_file("sa.json"), | ||
) | ||
|
||
def get(self, request: HttpRequest) -> HttpResponse: | ||
x_device_trust = request.headers.get(HEADER_DEVICE_TRUST) | ||
x_access_challenge_response = request.headers.get(HEADER_ACCESS_CHALLENGE_RESPONSE) | ||
if x_device_trust == "VerifiedAccess" and x_access_challenge_response is None: | ||
challenge = self.google_client.challenge().generate().execute() | ||
res = HttpResponseRedirect( | ||
self.request.build_absolute_uri( | ||
reverse("authentik_stages_authenticator_endpoint:chrome") | ||
) | ||
) | ||
res[HEADER_ACCESS_CHALLENGE] = dumps(challenge) | ||
return res | ||
if x_access_challenge_response: | ||
response = ( | ||
self.google_client.challenge().verify(body=loads(x_access_challenge_response)).execute() | ||
) | ||
# Remove deprecated string representation of deviceSignals | ||
response.pop("deviceSignal", None) | ||
flow_plan: FlowPlan = request.session[SESSION_KEY_PLAN] | ||
flow_plan.context.setdefault(PLAN_CONTEXT_METHOD, "trusted_endpoint") | ||
flow_plan.context.setdefault(PLAN_CONTEXT_METHOD_ARGS, {}) | ||
flow_plan.context[PLAN_CONTEXT_METHOD_ARGS].setdefault("endpoints", []) | ||
flow_plan.context[PLAN_CONTEXT_METHOD_ARGS]["endpoints"].append(response) | ||
request.session[SESSION_KEY_PLAN] = flow_plan | ||
return HttpResponse( | ||
"""<html><script> | ||
window.parent.postMessage({ | ||
message: "submit", | ||
source: "goauthentik.io", | ||
context: "flow-executor" | ||
}); | ||
</script></html>""", | ||
) |
Oops, something went wrong.