-
Notifications
You must be signed in to change notification settings - Fork 808
Session management #1543
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Session management #1543
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -315,6 +315,12 @@ Default: ``False`` | |
|
||
Whether or not :doc:`oidc` support is enabled. | ||
|
||
OIDC_SESSION_MANAGEMENT_ENABLED | ||
~~~~~~~~~~~~ | ||
Default: ``False`` | ||
|
||
Whether or not :doc:`oidc` support is enabled. | ||
|
||
OIDC_RSA_PRIVATE_KEY | ||
~~~~~~~~~~~~~~~~~~~~ | ||
Default: ``""`` | ||
|
@@ -353,6 +359,18 @@ this you must also provide the service at that endpoint. | |
If unset, the default location is used, eg if ``django-oauth-toolkit`` is | ||
mounted at ``/o/``, it will be ``<server-address>/o/userinfo/``. | ||
|
||
OIDC_SESSION_IFRAME_ENDPOINT | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why allow an iframe endpoint setting? It seems like this could become a support headache. Couldn't someone just override the url view if they wanted? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. To be honest I was just following the pattern established by the UserInfoView, which seems to do something similar? |
||
~~~~~~~~~~~~~~~~~~~~~~ | ||
Default: ``""`` | ||
|
||
The url of the session frame endpoint. Used to advertise the location of the | ||
endpoint in the OIDC discovery metadata. Changing this does not change the URL | ||
that ``django-oauth-toolkit`` adds for the userinfo endpoint, so if you change | ||
this you must also provide the service at that endpoint. | ||
|
||
If unset, the default location is used, eg if ``django-oauth-toolkit`` is | ||
mounted at ``/o/``, it will be ``<server-address>/o/session-iframe/``. | ||
|
||
OIDC_RP_INITIATED_LOGOUT_ENABLED | ||
~~~~~~~~~~~~~~~~~~~~~~~~ | ||
Default: ``False`` | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,8 @@ | |
} | ||
|
||
</style> | ||
{% block js %} | ||
{% endblock js %} | ||
</head> | ||
|
||
<body> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
{% extends "oauth2_provider/base.html" %} | ||
|
||
{% block title %}Check Session IFrame{% endblock %} | ||
|
||
{% block js %} | ||
<script language="JavaScript" type="text/javascript"> | ||
async function sha256(message) { | ||
// Encode the message as UTF-8 | ||
const msgBuffer = new TextEncoder().encode(message) | ||
|
||
// Generate the hash | ||
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer) | ||
const hashArray = Array.from(new Uint8Array(hashBuffer)) | ||
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('') | ||
} | ||
|
||
window.addEventListener("message", receiveMessage) | ||
|
||
async function receiveMessage(e) { | ||
// e.data has client_id and session_state | ||
if (!e.data || typeof e.data != 'string' || e.data == 'error') { | ||
return | ||
} | ||
|
||
try { | ||
const [clientId, sessionStateImage] = e.data.split(' ') | ||
const [sessionState, salt] = sessionStateImage.split('.') | ||
|
||
let userAgentState | ||
try { | ||
userAgentState = getUserAgentState() | ||
} | ||
catch (err) { | ||
userAgentState = '' | ||
} | ||
const knownImage = await sha256(`${clientId} ${e.origin} ${userAgentState} ${salt}`) | ||
|
||
const status = sessionState == knownImage ? 'unchanged' : 'changed' | ||
e.source.postMessage(status, e.origin) | ||
} catch(err) { | ||
e.source.postMessage(`error: ${err}`, e.origin) | ||
} | ||
} | ||
|
||
|
||
function getUserAgentState() { | ||
const cookieName = "{{ cookie_name }}" | ||
if (document.cookie && document.cookie !== '') { | ||
const cookies = document.cookie.split(';') | ||
for (var i = 0; i < cookies.length; i++) { | ||
const cookie = cookies[i].trim() | ||
// Does this cookie string begin with the name we want? | ||
if (cookie.substring(0, cookieName.length + 1) === (cookieName + '=')) { | ||
return decodeURIComponent(cookie.substring(cookieName.length + 1)) | ||
} | ||
} | ||
} | ||
throw new Error('OIDC Session Cookie not set') | ||
} | ||
</script> | ||
{% endblock %} | ||
|
||
{% block content %}OIDC Session Management OP Iframe{% endblock content %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OIDC_SESSION_MANAGEMENT_DEFAULT_SESSION_KEY
needs to be documented in the settings docs. What is it? Why is it needed to ensure consistent browser state? Is this a arbitrary string? Are there any security considerations for it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I understood it, the default key is meant to provide an unique value to the client_id, client_origin and session_identifier for users who are not yet authenticated and therefore have no request.session_key.
Without it, any user without a session would have different starting values for the session state, so the "get user agent state" would have different values for unauthenticated users.
I will add some more information in the docs for it.