Skip to content
Snippets Groups Projects
Unverified Commit 246ebc14 authored by Nimisha Asthagiri's avatar Nimisha Asthagiri Committed by GitHub
Browse files

Merge pull request #18139 from edx/arch/update-oauth-scopes-doc

Update OAuth decision 7: including organizations in tokens
parents 1c3eee27 e43f6370
No related branches found
Tags release-2020-03-16-08.06
No related merge requests found
......@@ -32,8 +32,7 @@ according to the organizational affiliation of the requesting application.
Organizational Types in the edX System
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the edX system, the 2 most prevalent organizational relationships
are:
Here are a few organizational relationships that exist in the edX system:
* **Organization as a Content Provider**
......@@ -55,8 +54,12 @@ are:
edX system, typically via an SSO-enabled portal, but with the
*organization (not edX) as the identity provider*. Such an
organization will also want to access data for all its users.
However, it is not an immediate requirement to support data
access by this organization type at this time.
* **Organization as a Credit Provider**
* This is an institution or employer that recognizes edX credentials for
a course, program, etc. A user would selectively grant organizations
permissions to access her edX records and information.
Decisions
---------
......@@ -65,9 +68,8 @@ In order to allow DOT Applications to access data for their own organization
without inadvertently or maliciously gaining access to data for other
organizations, (1) applications need to be linked to their own organizations,
(2) organization information needs to be cryptographically bound with
issued tokens, (3) the authorization approval form needs to present the
organization information and (4) organization limitations need to be
embedded in the scopes.
issued tokens and the (3) the authorization approval form needs to present the
organization information to the granting end-user.
1. Associate Available Organizations with DOT Applications
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......@@ -84,23 +86,36 @@ embedded in the scopes.
and DOT Applications.
* The new data model will also have a column for specifying organization
type: *content_provider* or *user_provider*. Initially, we will only
use *content_provider*.
type: *content_provider*, *user_provider*, *credit_provider*, etc.
Initially, we will only use *content_provider*.
2. Organization Information in OAuth Tokens
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2. Organization and Users as Filters in OAuth Tokens
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* The organization associated with the Application will be specified
in a new *filters* field in the JSON Web Token (JWT).
* The organization associated with the Application will be included
in the JWT tokens requested by the Application.
* The value of the *filters* field will include what *type* of organization
it is (per`Organizational Types in the edX System`_). For example:
"content_org:Microsoft"
* For a token created via a *Client Credentials grant type*, the token
is further restricted specifically for the granting user. And so, a
"user" filter with the value "me" would be added for this grant type.
For example:
"user:me"
* JwtBuilder_'s *build_token* functionality will be extended to include
the organization value in the token's payload. This payload is
the filters in the token's payload. This payload is
cryptographically signed and so binds and limits the scopes in the
token to the organization.
token to the filters.
* Since the organization value is inside the token, any relying party
that receives the token (including a microservice) will be able to
enforce scopes as limited to the organization.
* Since filters are inside the token, any relying party
that receives the token (any microservice) will be able to
enforce scopes as limited by the filters. API endpoints will limit the
values returned in their payloads by the specified filters.
.. _0006-enforce-scopes-in-LMS-APIs: 0006-enforce-scopes-in-LMS-APIs.rst
.. _Organization: https://github.com/edx/edx-organizations/blob/fa137881be9b7d330062bc32655a00c68635cfed/organizations/models.py#L14
......@@ -115,51 +130,42 @@ associated with an Organization, the Organization value(s) should be
presented to the user. This makes it clear to the user that the
granted access is limited to the Organization's affiliations.
4. Embed Organization Limitation Types in Scopes
Token Examples
--------------
Client Credentials (server-to-server) grant type
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Since individual API endpoints need to enforce both scopes and their
corresponding organization limitations as included in the token, the
scopes themselves should indicate whether or not organization limitations
apply.
* In the event that we add additional types of organization limits in
the token, we would introduce new scopes that enforce the new
types of limits.
* This allows us to introduce new types of limits while being assured
that pre-existing API endpoints will remain protected. Since the
pre-existing endpoint is unaware of the new scope, it will
prevent access until it is updated to support the new type of
organization limit.
Scopes Examples
---------------
Here is an initial list of scopes that we may support. Notice how some
enforce organization limits and others don't. When configuring a DOT
Application, the edX operator decides how much access the application
is permitted.
+-------------------------------+----------------------------------------------------------------+
| Scope | Allowed access |
+===============================+================================================================+
| certificates:read | Retrieve any certificate |
+-------------------------------+----------------------------------------------------------------+
| certificates:read:content_org | Retrieve certificates for courses provided by the organization |
+-------------------------------+----------------------------------------------------------------+
| grades:read | Retrieve any grade |
+-------------------------------+----------------------------------------------------------------+
| grades:read:content_org | Retrieve grades for courses provided by the organization |
+-------------------------------+----------------------------------------------------------------+
| enrollments:read | Retrieve any enrollment information |
+-------------------------------+----------------------------------------------------------------+
| enrollments:read:content_org | Retrieve enrollments for courses provided by the organization |
+-------------------------------+----------------------------------------------------------------+
**Note:** Each of these scopes can be used in a server-to-server
API call (via Client Credentials) or an API call on behalf of a
single user (via Authorization Code).
When a trusted application makes server-to-server calls, the application's
service user info is included in the JWT and the *filters* field
includes the organization identifier and type associated with the application.
::
{
"scopes": ["grades:read", "enrollments:read"],
"filters": ["content_org:Microsoft"],
"version": "1.0",
"preferred_username": "microsoft_service_user",
...
}
Authorization Code and Password-based (on behalf of user) grant types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When a user-approved application or a trusted mobile app makes calls on behalf
of the approving user, the user's info is included in the token along with a
filter “me” in the *filters* field.
::
{
"scopes": ["grades:read", "enrollments:read"],
"filters": ["content_org:Microsoft", "user:me"],
"version": "1.0",
"preferred_username": "ajay_mehta",
...
}
Consequences
------------
......@@ -168,14 +174,45 @@ Consequences
Applications, we can eventually eliminate Restricted Applications
altogether.
* By including the organization value in the token, any relying party
* By including the organization value and its type in the token, any relying party
that receives the token (including a microservice) will be able to
enforce the scopes as limited to the organization.
* Including the organization limitation types in the scope allows for
a secure path forward to introduce new types of limitations in the
future. It also makes it clearer to API endpoints what needs to be
enforced.
* Having a separate field for *filters* introduces a clear boundary for
separation of concerns of what is enforced at each layer:
* **API endpoint** declares the *required scopes*.
* The base **Django Permission** class enforces *required scopes*.
* **API gateway** (in the future) may additionally enforce *required scopes*.
* **API endpoint** enforces the *required filters*.
* When a new filter type is introduced in the future, we will have to
make sure there are no security issues introduced where old endpoints
that are not aware of the new filter do not enforce it. Possible
ways of doing so are:
* Endpoints that are highly security sensitive should reject any
token that includes an unrecognized filter.
* Multi-phase rollout with a major version update of tokens once all
microservices and relevant endpoints have updated to recognize the new
filter. Tokens with the new filter would be issued only after all relevant
endpoints have been updated.
* Alternatively, we could have embedded the filter-type within the *scopes*
field of the token. This would support a more secure path forward since
old endpoints would automatically reject new filter-types in scopes that
they don't recognize. For example:
"grades:read:content_org"
Additionally, this alternative would allow tokens to specify different filters
for different scopes.
However, this alternative was rejected since it added unnecessary confusion
in understanding and parsing scope values. Additionally keeping filters
independent allows them to evolve and grow (more complex) over time without
trying to coerce their values within scope expressions.
References
----------
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment