Giter Club home page Giter Club logo

authx's Introduction

AuthX

This is AuthX. It's named AuthX because it's an "exchange" of sorts, consolidating identities from several upstream authorities into a single identity for downstream clients. AuthX uses the OAuth2 framework in both directions, and adds a robust access control system, based on the AuthX scope spec.

Build Status FOSSA Status

FOSSA Status


Contributing

Please see CONTRIBUTING.md.


Packages

This is a monorepo that contains several useful node packages:

AuthX

The AuthX package contains the core application and API manages users, credentials, roles, clients, authorities, grants, and tokens.

Read More

HTTP Proxy - Client

This package includes an HTTP proxy which can be used by a client in a trusted context (such as a private network) to inject credentials into a request. This eases incremental adoption of AuthX, allowing clients to remain unaware of the authorization layer.

Read More

HTTP Proxy - Resource

This package includes an HTTP proxy which can be put in front of a resource. It verifies and caches access tokens, manages public keys, and injects verified scopes directly into the proxied request.

Read More

HTTP Proxy - Web

This package includes an HTTP proxy which can be put in front of a web client. It takes on the responsibility of managing OAuth flows, and can inject credentials into the proxied requests to resources.

Read More

Interface

The AuthX Interface is a reference user interface that provides the visual components necessary for a user to authenticate herself and authorize a client to access resources on her behalf.

The small, react-powered app features a pluggable architecture that can be used to support additional authorization strategies.

Read More

Scopes

This package contains a small collection of utility functions for AuthX scopes. These scopes are human-readable, fully OAuth2-compatible, and support both pattern matching and set algebra.

Read More

Strategy - Email

This package contains the email authentication strategy.

Read More

Strategy - OpenID

This package contains the OpenID authentication strategy.

Read More

Strategy - Password

This package contains the password authentication strategy.

Read More

Tools

This package contains a CLI and small collection of utility functions for interacting with an AuthX instance.

Read More

authx's People

Contributors

dependabot-preview[bot] avatar dependabot[bot] avatar ebrown32 avatar ethankent avatar fossabot avatar mike-marcacci avatar nickcarenza avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

authx's Issues

Add implied scopes to OAuth 2 authorization token requests

The scope authx:authorization.equal.self.granted:** is required for the OAuth 2 authorization token flow. This has been a source of confusion that could easily be remedied by automatically adding this scope to the OAuth 2 request.

Break out strategies into their own projects.

These strategies are for external providers and probably belong in their own repos. This will help enforce the desired separation between components, and provide a template for creating others.

Add request events to proxies

AuthX proxies are a perfect place to standardize logs in a complex distributed system. The proxies should emit an event for each request with sufficient information for logging.

Provide a `close` method

Provide a way to clean up resources (like open pg connections) to help support graceful shutdown.

Add reference UI

Right now we have our own internal UI pieces for signing in, managing roles, etc. We should create a public reference UI so that it's clear how this should be used.

Break "scopes" util out into its own repo.

The scopes logic is useful (needed) for anything that integrates with AuthX and is the gatekeeper of a resource. These apps shouldn't be forced to import all of AuthX just to get the util, and there are also good use cases for scope utils beyond an AuthX integration.

Accordingly, we should break it out into its own package and require it in AuthX.

Context should hold a postgres pool instead of connection

Now that we're implementing multi-entity updates (see #38) we have a need to run multiple transactions in parallel. To enable this, the GraphQL context should have a pool field with the connection pool, rather than a tx field with a single connection.

Make sure all strategies can connect new credentials to existing users

Right now new credentials can be added via CRUD endpoints, given the correct permissions. However, it is not possible for a user to, for example, directly associate multiple Google accounts without determining her additional Google IDs out-of-band.

All strategies (and AuthX itself) should support automatic attachment of new credentials to existing sessions (and the currently authenticated user).

Add basic filters to lists

We need to be able to filter lists based on various criteria. In particular, we need to be able to include/exclude disabled entities.

Add a "current" scope to authorizations

Adding the scope:authorization.equal.self.granted: gives us the ability to restrict accessing authorization secrets to the one currently in use, limiting the potential reach of a compromised user authorization.

Add loading indicators to authx interface

The AuthX interface currently doesn't display any loading indicators, which can be confusing when it spends a second making OAuth requests or waiting on the API to run bcrypt.

Add FOR UPDATE option in models/mutations

Right now we have to run postgres in "serializable" isolation level to guarantee correctness; instead the model layer should accept a forUpdate flag in their read method, which mutations can then use when reading an entity in the context of a mutation.

SELECT ... FOR UPDATE

Add SAML strategy

We already have a need for a SAML authorization strategy. For our particular case, these credentials will need to be created by the SCIM provisioner, so this feature should help inform design decisions for #56.

Add SCIM client

It's quite likely that we will need to use AuthX to provision downstream systems, and SCIM is an ideal standard for doing this.

This is also the perfect full-featured test case for an extension mechanism (#52).

Add http-proxy-authorization

We currently have proxies that sit in front of resources and clients. A third need is for scenarios in which a program needs to access a resource, but doesn't want to deal with the authorization flow. For this case, we need a proxy which can inject a token into the request.

Restrict scope assignment by the current user's scopes

Right now access to the following scopes theoretically bestow unlimited access. AuthX should ensure that any added/modified scopes fall within the current user's access so that she cannot, for example, assign herself additional abilities.

  • AuthX:role.<role_id>:update.scopes
  • AuthX:client.<client_id>:update.scopes

Allow optional specification of IDs when creating entities

Currently, AuthX assigns IDs to newly-created entities. This means that you would have to make multiple requests to, say, add a user, and then assign the user to a role (since you need the user’s ID to assign to the role). Because we used UUIDs here, we can make it so that a GraphQL client can optionally specify an ID when creating a new entity. This will enable batching of mutations that include entity creation.

Return a koa-router object instead of an app

When AuthX was first created, Koa 2 wasn't even in alpha yet, and koa-router was incompatible with the new promise-based architecture. It's since been updated to work with Koa 2, and we should return a router object instead of an app, to make it more easily embedded in parent apps.

This will also allow us to remove our custom routing utility, further simplifying the codebase.

Add a "manager" UI

TCG is currently building an in-house management UI for AuthX. Once this is complete, we should consider extracting its generic functionality for the benefit of the broader AuthX community.

This repo has a stubbed-out package called @authx/manager for this purpose.

Add a worker package for expiring/forcing rotation of authorizations & grant secrets

A big (and growing) part of security is risk prediction and preemption. With AuthX, it is good practice to revoke likely leaked, long-unused, or suspicious authorizations and grant secrets. Of course, these rules are all specific to the application and organization use cases, so instead of implementing every conceivable strategy here (impossible) and providing a host of config options (messy) we should just provide a sample plugin which collects basic metadata and revokes keys based on simple criteria like "revoke authorizations of human users that have gone unused for more than 30 days." Real-world applications could follow this pattern and use whatever additional information is available to them, given their context.

UnhandledPromiseRejection in `fetchAccessToken`

In the catch block below, retry requests are made in a timeout, but the parent context continues to execute and throw an error (Promise rejection). Each successive failure will add another call to the stack, infinitely, while also causing Node to log an UnhandledPromiseRejectionWarning. In the future, this will just cause the Node process to exit.

https://github.com/the-control-group/authx/blob/master/packages/http-proxy-client/src/index.ts#L594

Handling the error is the immediate need, but also during the fix it might be beneficial to provide some options to retry X times before failing the initial request to handle miscellaneous network errors without additional retry logic in the proxy's parent application.

Add an audit log

One of the final pieces for AuthX 2.0 is the creation and publication of an audit log. The schema itself already enforces this for writes, but we are currently not tracking reads or failed attempted writes.

  • Track all writes
  • Come up with schema for audit logs, including reads and rejected attempts
  • Come up with API for exposing this over GraphQL
  • Come up with scopes for restricting access to audit log

Add "secret" strategy

It makes sense for API type users in particular that they would want first-party access to their own access tokens. We should add a "secret" strategy that functions identically to the "password" strategy, but returns an access token to the browser.

Update strategy types to reference linked types

Current, openId authorities can be configured with the email provider ID that they can use. In the API response, however, they return the ID instead of a reference. Let's make this idiomatic and return a reference.

Add "redirecting" loader to interface

After granting access to a client, the "Authorize" screen is displayed while redirecting, which is confusing. Instead, we should display "Redirecting..." or a similar indicator.

Make sure permissions respect the configured realm

There's a "realm" config option that allows changing the realm to be something other than AuthX (like your app's name). Right now this isn't used in the scopes tried by the controllers. It needs to be there to be useful.

Instead of "AuthX:role.*:read" it should be ctx.app.config.realm + ":role.*:read".

Add SCIM server

We have a need to provision AuthX accounts using SCIM. We had done this previously on v1, and will need to do this again shortly.

After considering the extension mechanism described in #52, it's become clear that instead of providing an additional API that uses models directly, this should instead make GraphQL requests to the AuthX server. This way we avoid bypassing any registered extensions (which will be applied at the GraphQL layer).

More granular user management scopes

Right now user management is more or less all-or-nothing. This is probably not ideal in an organization with any hierarchy. Our options include:

1. Restrict by "team"

AuthX:user.<team_id>:**
Teams are really a half-baked feature right now and I'm hesitant to depend on them too much for core functionality. Additionally, right now a user can change his/her team without any special permissions (this was one of the goals of the team model). We could, however, update their meaning and give the ability to change one's team its own scope.

The problem here is with hidden loopholes: someone may be able to reset the password of (or otherwise impersonate) a team member who has higher levels of access, thereby gaining access herself. Because teams do NOT correspond directly to roles (which are necessarily flat), a moderately complex organization could quickly begin exposing itself to vulnerability as teams and roles evolve.

2. Restrict by "scopes"

AuthX:user.<superior | peer | subordinate>:**
Because AuthX is aware of every user's scopes, it can trivially compare the abilities of one user to another. Instead of shifting the complexity to the users, who would under option 1 need to design their roles/teams accordingly, we could divide the users by relationship: superior, peer, subordinate. This way, if a user is given specific (perhaps initially temporary) access to a scope, her supervisors are not inadvertently also given such access.

Add scope filtering to rethinkdb queries

While working on #2 I've added many, many opportunities to optimize (ie. reduce) queries to related models (users and roles in particular).

For example, a query to /v1/grants will get all grants from the database, then get all associated users and associated roles to determine the relationship of the current user to each grant. While this could certainly be optimized app-side, our scopes are already converted to javascript RegExp objects, and RethinkDB can efficiently join in other tables and run the regular expressions.

We should explore a way to enforce permissions in our queries for a potentially massive performance gain.

Use httpOnly cookies for http-proxy-web

There was an initial goal of enabling the front-end to directly use the AuthX tokens/etc. However, it's now clear that this is unnecessary, and we could achieve tighter security controls by restricting access to client-side JS.

To go further, we could encrypt the values, which would prevent tokens leaked from an insecure browser from being used against resources directly (they would have to use the proxy). This, however, is probably outside our current threat model at the moment.

Add support for revocable tokens in resource proxy

Currently, the resource proxy only supports authorization via bearer tokens. This is the ideal production scenario, but adds considerable friction when testing or debugging a resource as a developer.

The proxy should support the same two mechanisms supported by AuthX itself: BEARER and BASIC, using an AuthX Authorization's id and secret as the "username" and "password" for basic authentication.

Remove babel and require node v7.x

The compilation step here is a real pain. Given that nodejs v7 supports async/await with the --harmony flag, and this only sees internal use (as far as we know), we should completely remove babel and older versions of node as targets.

This will make work on other issues far easier, and greatly lessen the learning curve for new developers.

Rewrite the OAuth2 API to make GraphQL requests

After considering the extension mechanism described in #52, it's become clear that instead of providing an additional API that uses models directly, this should instead make GraphQL requests to the AuthX server. This way we avoid bypassing any registered extensions (which will be applied at the GraphQL layer).

Allow users to manage granted scopes

Right now there is an all-or-nothing "Grant Access" or "Deny". This is a bit too blunt of an instrument for our use cases, and instead the user should be able to toggle (or possibly even write) which scopes to grant.

Return better error on password uniqueness collision

The “password” strategy explicitly enforces that there’s only one per user. Instead of returning a generic "Internal Server Error" when creating a duplicate, we need to return a better message like, “There can only be one active password for a user.”

Add revocableTokenCacheDuration to resource proxy

If revocableTokenCacheDuration is configured, the proxy will cache the result of the introspection request for the configured number of seconds. Note that proxy instances do not share a cache, so a recently-revoked authorization may have different behavior between instances.

  /**
   * The number of seconds for which the proxy will cache the AuthX server's
   * token introspection response for a revocable token.
   *
   * @defaultValue `60`
   */
  readonly revocableTokenCacheDuration?: number;

Create a generic extension mechanism

There are many instance-specific features (logging, notifications, risk mitigation, external provisioning etc) which could benefit from a standard mechanism for extending AuthX.

In particular, they should be able to modify or prevent a request's behavior, in addition to performing external tasks in response to a request.

It's likely that an approach like graphql-middleware will fit the bill (although I personally dislike some of their API choices).

Add "records" to the API

Every version (or "record") of each entity is immutable. We need to think through and implement a way to expose this information over the API.

One thing we obviously have to think through is access control. My initial reflex is to apply the permissions from an entity's current record to all past records. However, we need to be careful about leaking metadata: prehaps having access to read basic information about a client shouldn't convey access to its change history – even if only basic information is exposed in those records. We also need to be careful about inferences made with this metadata: by having access to basic read information but NOT secrets, one may still be able to infer that a secret was changed when a new record exists but no basic information has changed. (As a counter to this, though, we do currently store new records when an update call is made but which doesn't in fact result in changes... so this partial metadata is insufficient for a strong inference in this regard.)

Another thing we need to consider is how the data is represented – either as states, or as diffs. We may be able to punt on this, and simply display metadata: timestamp, responsible authorization, previous record, next record.

Add relay-style "Connections" to lists

I had been hoping that we could get away with simple offset/limit pagination, particularly because all the extra objects can be a bit overwhelming to GraphQL newcomers... however, it appears that TCG may be interested in adopting GraphQL in places where this is not feasible, and cursor-based pagination will be necessary. The latter is a far superior way of addressing the problem, so if the learning is going to happen, we might as well begin enforcing this best practice here.

Because it is such a well-establiished convention, we will follow the semantics outlined in relay's connection spec. Until this RFC lands in GraphQL, it will be impractical to describe this as an interface, and we will instead have to just follow the naming scheme.

Query users by role IDs

Right now the user endpoints inconsistently look for the query parameters roles and role_ids to restrict the results to specified roles. References to roles should be updated to use the role_ids parameter.

Add rfc7662-compliant token introspection endpoint

Currently, a revocable token is passed as HTTP Basic credentials in the Authorization header. The authorization ID is used as the "username" and the authoriztion secret is used as the "password". For this to be possible, the authorization must include the scopes authx:authorization.equal.self.current:read.basic and authx:authorization.equal.self.current:read.scopes.

We need to consider a mechanism for supporting token introspection requests that follow rfc7662.

Currently, as there is no registration of resources, this isn't possible without deviating from the RFC's security recommendations.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.