Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

This page is starting as a collection of notes, design decisions, etc. related to implementing OAuth2 into Synapse. Part of the process has included considerations about developing our own library, or using an off-the-shelf solution like ORY Hydra. The information on this page may change as the project evolves.

See also: Bruce Hoff's presentation on his preliminary research into OAuth2 and how it relates to Synapse.

More reading: Synapse as OAuth 2.0 Provider

And a Jira Epic:  PLFM-4585 - Getting issue details... STATUS

Use cases

High level use-cases, per Bruce Hoff's presentation:

  1. Let third party (web) app’s securely access a user’s data in Synapse.  Today such app’s must either
    1. predownload/embed data,
    2. use the app’ author’s Synapse credentials, or
    3. prompt the user for their Synapse credentials
  2. Let a headless batch job (e.g.,a “workflow”) securely access a user’s data in Synapse.  Today such a process must either
    1. Use predownloaded data
    2. Use the job runner’s Synapse credentials

These use cases must guide how we encode scope.

Some questions:

  • How granular do we expect scope must be? 
    • Do Read/Edit/Write permissions cover all use cases?
    • Can 

Basic OAuth or OAuth-like flow (authorization grant only, no external tools)

To implement the bare minimum to address use cases with an OAuth-like flow, we need

  • Endpoints to create, read, list, delete (and optionally, update) clients
  • Authentication code generation
VerbEndpointPurposeInput Object/ParamsReturn Object/ParamsNotes
GET/oauth2/clients

Get a list of all clients



Client API access can be restricted based on our needs.

  • All registered Synapse users?
  • Approved OAuth API users?
  • OAuth Administrators?
GET/oauth2/clients/{id}Get details about one clientid: a client ID

POST/oauth2/clientsCreate a client

what information do we need from a client?

client object

client object + secret key (do not store the secret key)


DELETE/oauth2/clients/{id}Delete a clientclient ID-





Can Synapse authenticate users with existing endpoints and services? Do we need new ones?
GET/oauth2/authorize

Prompt user for request when they call this.

Show as much relevant information  as possible (X app wants Y permission on Z resource)

client (ID)
request_url (String)
requested_scope (array of string)

Web interface for Synapse authorization

Verify here if the user can actually grant the scope they request? If we support granting scope to particular entities, when should we make sure the user has access to the entity? Upon authorization token request? Upon attempt to access the entity with the token?
POST/oauth2/authorizeUser must accept or decline request

client (ID)
request_url (String)
requested_scope (array of string)

LoginRequest

Redirect URL containing authentication code tied to the input client ID and the scope

LoginResponse?

How to handle with various Synapse IdPs? (E.g. Synapse users who sign in with Google accounts)
GET/oauth2/tokenCalled by a client to get a token with an authorization code

authorizationCode

authentication token
refresh token


POST/oauth2/token/refreshCalled by a client to refresh an authentication tokenrefresh_tokenauthentication_token


Many Existing APIS must now support Authorization tokens?


GET/oauth2/token/introspectClients can determine if an authentication token is valid

This may not be necessary (but could provide a lot of utility to clients)






Diagram from the above presentation, edited to show where these API endpoints would be used:

What is "scope"?

JIRAs(?):  PLFM-5170 - Getting issue details... STATUS

In short: scopes are clearly defined permissions that a user may grant to an OAuth client.

In ORY Hydra, OAuth clients may be limited in the scope they can request (e.g. a photo printing service (OAuth client) may be restricted to only acquire read-photo permission, even if they attempt to request edit-photo permission). This is not a requirement of our implementation, but it is worth consideration.

From RFC-6749

The authorization and token endpoints allow the client to specify the scope of the access request using the "scope" request parameter.  In turn, the authorization server uses the "scope" response parameter to inform the client of the scope of the access token issued.

The value of the scope parameter is expressed as a list of space-delimited, case-sensitive strings. The strings are defined by the authorization server. If the value contains multiple space-delimited strings, their order does not matter, and each string adds an additional access range to the requested scope. scope = scope-token *( SP scope-token ) scope-token = 1*( %x21 / %x23-5B / %x5D-7E )
The authorization server MAY fully or partially ignore the scope requested by the client, based on the authorization server policy or the resource owner's instructions. If the issued access token scope is different from the one requested by the client, the authorization server MUST include the "scope" response parameter to inform the client of the actual scope granted. If the client omits the scope parameter when requesting authorization, the authorization server MUST either process the request using a pre-defined default value or fail the request indicating an invalid scope. The authorization server SHOULD document its scope requirements and default value (if defined).

The actual encoding and representation of scope is not necessarily within the scope of this document (ha ha), but it is something that will likely strongly guide our implementation of OAuth. Naturally, how we design scope should be informed by use cases. We should methodically determine what access we wish to grant OAuth2 clients, as well as how much granularity (both breadth of permissions and Synapse object access) we can/should reasonably encode. Additionally, this should be informed by how we have designed and use ACLs, since this paradigm of authorizing access to content in Synapse is likely to be the driver of OAuth-based content authorization.

An OAuth2 client developer must be able to determine the scope that they need when designing their OAuth2 client service, so it is also critical that we document 

Examples of OAuth2 scope documentation in the wild:

If we choose to be ultra-granular with scope (e.g. only granting read access to one particular file, with a permission structure like read:syn123), we will likely have to store these scopes in a database. One implementation option is to make scope a UUID and store the actual scope information in a database; the downside: client developers may have to generate scope UUIDs on-the-fly. This also seems to conflict with the design decisions of other OAuth providers (see external documentation samples above).

ORY Hydra

This is a good place to collect information and research relevant to using ORY Hydra to implement OAuth2 and OIDC in Synapse. This portion of the document is not complete, and may not be completed if we choose not to use ORY Hydra to implement OAuth2.

Why ORY Hydra:

Per Bruce Hoff's preliminary research, ORY Hydra is one of very few (and perhaps the only) established, off-the-shelf OAuth2 + OIDC solution that delegates authorization provider and resource provider roles to external services. Since Synapse already has this infrastructure in place (excepting interfaces for OAuth2 authorization flow), we can use Hydra to handle some of the more complicated parts of implementing OAuth2 and OIDC, and create our own authorization/resource provider services that use existing Synapse infrastructure.

Why NOT ORY Hydra:

To be expanded upon later, and points may be focused upon later in this document.

  • Possible future maintenance costs, incompatibilities with our infrastructure, and other tech-debt related concerns
  • Overkill for our use case?

Does Hydra work with our use cases?

For example, can we implement our proposed scope pattern into Hydra? What other constraints exist in Hydra that may be major roadblocks? 

ORY Hydra in the wild

Can we find cases of other engineers using Hydra?

What problems have they run into?

What benefits have they seen that Hydra provides?

What other potentially crucial information about Hydra can we find on the internet?

Decisions and requirements to deploy via Cloudformation

See:

PLFM-5163 - Getting issue details... STATUS  

Internal configuration

We should tailor ORY Hydra's configuration to meet our needs

Database

Per the ORY Hydra docs:

The SQL adapter supports two DBMS: PostgreSQL 9.6+ and MySQL 5.7+. Please note that older MySQL versions have issues with ORY Hydra's database schema. For more information go here.

If my understanding is correct, the DB that Hydra uses is entirely separate from other services, so it should not be a concern here that Synapse currently uses MySQL 5.6

One concern here is that ORY Hydra requirements may evolve to conflict with other constraints. For example, Hydra may have a security flaw that is only patched by upgrading to a database service that is not provided by Amazon RDS.

Infrastructure Configuration

For reliability, we will want to deploy two instances of ORY Hydra behind a load balancer.

Is Hydra truly stateless? Can we safely configure it behind a load balancer?

How does Hydra "federate" identity providers? Should we configure Hydra differently to interact with Synapse u:p vs. Synapse users that use Google SSO via OAuth? Or delegate that complexity to a Synapse Authentication provider?

Choosing an ELB type

AWS offers three different types of load balancers, described further in this AWS document.

  • Application Load Balancer
  • Network Load Balancer
  • Classic Load Balancer (formerly Elastic Load Balancer)

Also worth looking into (if relevant?) is the Elastic Container Service.

VPC

Per the ORY Hydra docs, ORY Hydra has two ports, a public port, and an administrative port. I think the VPC/ELB should forward requests over TLS/443 to the public port.

The administrative port should not be exposed to public internet traffic. If you want to expose certain endpoints, such as the /clients endpoint for OpenID Connect Dynamic Client Registry, you can do so but you need to properly secure these endpoints with an API Gateway or Authorization Proxy. 

Do we need this?

Spring Security

More on this later

  • No labels