Metadata-Version: 2.1
Name: openedx-forced-login-redirection
Version: 0.2.1
Summary: Forced Third-party Authentication before redirects on Open edX
Home-page: https://github.com/academic-innovation/openedx-forced-login-redirection
Project-URL: Documentation, https://academic-innovation.github.io/openedx-forced-login-redirection/
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Django :: 3.2
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: django>=3.2
Requires-Dist: edx-django-utils

# openedx-forced-login-redirection
A super-simple, safe internal URL redirection scheme for forcing authentication before
loading a resource in Open edX.

There are two places where this is valuable:
- Directly linking to resources from outside of the platform (e.g. emails) that we want
  to ensure authenticated access to.
- Ensuring that a linked user follows through with a specific Third-Party Auth profile.

## Basic Modes

There exist two different strategies for creating links to views within the platform.

### Param-based

In this case, the app creates a simple URL pattern, and the view expects the a query
parameter named `next`, which contains the path to the selected resource. Nominally this
should be an absolute path to a known URL on the platform, but it could be a complete
URL, as long as the hostname of the URL matches the hostname of the request.

The path is validated for availability within the platform before any redirects happen.
If the path is definitely not available within the platform, an HTTP 400 error is
returned.

#### Manual-usage Example

Mount one of the provided views at a top-level URL `/platform-redirect/`:

```python
from django.urls import path

from login_redirection import views

urlpatterns = [
    path("platform-redirect/", views.tpa_redirect_param),
]
```

If there's a known path on the platform at, say, `/course/MyCourse/about`, you would
craft a URL as:

```
https://edx.example.com/platform-redirect/?next=/course/MyCourse/about
```

### Path-based

In this case, the app has a URL pattern that captures the tail end of a URL path, and
treats it as the reference path. In other words, it allows one to take any path within
the platform and prefix it with a custom mount point, making a slightly more pleasant
URL.

The path is validated for availability within the platform before any redirects happen.
If the path is definitely not available within the platform, an HTTP 404 error is
returned.

#### Manual-usage Example

Mount one of the provided views at a top-level URL `/platform-redirect/`:

```python
from django.urls import re_path

from login_redirection import views

urlpatterns = [
    re_path(r"^platform-redirect(?P<path>/.*)$", views.tpa_redirect_path),
]
```

If there's a known path on the platform at, say, `/course/MyCourse/about`, you would
craft a URL as:

```
https://edx.example.com/platform-redirect/course/MyCourse/about
```

## Ensuring Authenticated Requests

In many cases within Open edX, a view may respond with an unauthenticated view.
Sometimes just taking a user to an authenticated page is the desired behavior. Views
available are:

<table>
<thead>
<tr>
<th>View type</th>
<th>View name</th>
<th>Default url path</th>
<th>Default url name</th>
</tr>
</thead>
<tbody>
<tr>
<td>Param-based</td>
<td><code>login_redirection.views.ensure_auth_redirect_param</code></td>
<td><code>authenticated/</code></td>
<td><code>login-redirection:ensure-auth</code></td>
</tr>
<tr>
<td>Path-based</td>
<td><code>login_redirection.views.ensure_auth_redirect_path</code></td>
<td><code>authenticated/&lt;path&gt;</code></td>
<td><code>login-redirection:ensure-auth</code></td>
</tr>
</tbody>
</table>

## Forced Third Party Auth Requests

For some cases where launching an interaction from a catalog app to the platform,
forcing a Third-Party Auth is valuable to ensure that the logged-in user is consistent.

In these cases, a redirect to login will always happen, along with an automatic trigger
to authenticate to a specified authentication provider. The views are available at:

<table>
<thead>
<tr>
<th>View type</th>
<th>View name</th>
<th>Default url path</th>
<th>Default url name</th></tr>
</thead>
<tbody>
<tr>
<td>Param-based</td>
<td><code>login_redirection.views.tpa_redirect_param</code></td>
<td><code>tpa/</code></td>
<td><code>login-redirection:tpa-redirect</code></td>
</tr>
<tr>
<td>Path-based</td>
<td><code>login_redirection.views.tpa_redirect_path</code></td>
<td><code>tpa/&lt;path&gt;</code></td>
<td><code>login-redirection:tpa-redirect</code></td></tr>
</tbody>
</table>

### Specifying the authentication provider

#### URL Parameter

In all cases, the `tpa_hint` parameter is honored, if present. This also digs down into
the specified redirect URL, so if a `tpa_hint` is already embedded, it will be honored.

#### Specifying a default in `settings`

The `LOGIN_REDIRECTION_DEFAULT_TPA_HINT` setting can be used to specify a specific TPA
provider without having to hand a `tpa_hint` parameter. If it is not set, and no
`tpa_hint` is provided as mentioned above, the result is an HTTP 400 error.

## Use as an Open edX Plugin

This Django App is usable as an Open edX Plugin. It mounts the default URL patterns to
the root of the `lms` platform only. No default setting is provided for
`LOGIN_REDIRECTION_DEFAULT_TPA_HINT`.

## Modifying Default URLs with `settings`

Settings are available to manage views mounted in the default URL patterns.

<table>
<thead>
<tr>
<th>View</th>
<th>Enabled Setting</th>
<th>Prefix Setting</th>
<th>Default Prefix</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>views.ensure_auth_path</code></td>
<td><code>LOGIN_REDIRECTION_ENSURE_AUTH_PATH_ENABLED</code></td>
<td><code>LOGIN_REDIRECTION_ENSURE_AUTH_URL_PREFIX</code></td>
<td><code>authenticated</code></td>
</tr>
<tr>
<td><code>views.ensure_auth_param</code></td>
<td><code>LOGIN_REDIRECTION_ENSURE_AUTH_PARAM_ENABLED</code></td>
<td><code>LOGIN_REDIRECTION_ENSURE_AUTH_URL_PREFIX</code></td>
<td><code>authenticated</code></td>
</tr>
<tr>
<td><code>views.tpa_redirect_path</code></td>
<td><code>LOGIN_REDIRECTION_TPA_PATH_ENABLED</code></td>
<td><code>LOGIN_REDIRECTION_TPA_URL_PREFIX</code></td>
<td><code>tpa</code></td>
</tr>
<tr>
<td><code>views.tpa_redirect_param</code></td>
<td><code>LOGIN_REDIRECTION_TPA_PARAM_ENABLED</code></td>
<td><code>LOGIN_REDIRECTION_TPA_URL_PREFIX</code></td>
<td><code>tpa</code></td>
</tr>
</tbody>
</table>

For instance, if we only wanted to support a single endpoint to ensure auth via a path
rooted at `ensure-auth`, one could configure the settings as:

```
LOGIN_REDIRECTION_ENSURE_AUTH_URL_PREFIX = "ensure-auth"
LOGIN_REDIRECTION_ENSURE_AUTH_PATH_ENABLED = True  # See Note 1
LOGIN_REDIRECTION_ENSURE_AUTH_PARAM_ENABLED = False
LOGIN_REDIRECTION_TPA_PATH_ENABLED = False
LOGIN_REDIRECTION_TPA_PARAM_ENABLED = False
```
> 1 This setting is not necessary, as all views are mounted by default, but is 
> included here for clarity.
