Git Product home page Git Product logo

oidc-op's Introduction

NOTICE

We’re archiving Anvil Connect and all related packages. This code is entirely MIT Licensed. You’re free to do with it what you want. That said, we are recommending against using it, due to the potential for security issues arising from unmaintained software. For more information, see the announcement at anvil.io.

OpenID Connect for Nodejs

Build Status codecov

This library aims to implement a full-featured OpenID Connect Provider for Nodejs. It is not intended to be used directly by most developers, but rather via a complete self-contained server such as Anvil Connect. Some applications require an embedded identity provider, such as entertainment or IoT appliances. This package can be used directly in these cases.

The module should make available an OIDCProvider class which can be instantiated multiple times to support multitenancy use cases. It should also have a method that provides a mountable router or app for widely used frameworks like Express.

Scope

  • Core
  • Discovery
  • Dynamic Registration
  • OAuth 2.0 Multiple Response Types
  • OAuth 2.0 Form Post Response Types
  • Session Management
  • Front-Channel Logout
  • Back-Channel Logout
  • OAuth 2.0 Client Credentials Grant
  • Proof Key for Code Exchange by OAuth Clients (PKCE)
  • Authorization Cross Domain Code (ACDC)

Dependencies

This package is a work in progress, dependent on other ongoing projects. Code contained herein will be completed when the following dependencies are ready to release:

Tentative Scope

  • Account Chooser 1.0
  • Native Applications Agent Core 1.0
  • Native Applications API Bindings 1.0

Out of Scope

  • Local Authentication
  • Persistence

Internal Interface

OpenID Connect makes no provisions for how a user is initially authenticated by the IdP. It's up to the implementer to determine whether to use passwords, LDAP, SAML, OAuth, or some other means. The host system is responsible for other dependencies of the OIDC authentication flows as well, such as persistence, managing user attributes, multi-factor auth and so on.

In addition to implementing OpenID Connect Provider functions, this library defines an interface between OpenID Connect and the host application.

The goal of the interface is to manage the flow of responsibility between the OpenID Connect implementation and functions provided by the host application, such as local user authentication, persistence, and domain specific event handing.

MIT License

Copyright (c) 2016 Anvil Research, Inc.

oidc-op's People

Contributors

christiansmith avatar dmitrizagidulin avatar eternaldeiwos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

oidc-op's Issues

Preserve redirect_uri hash fragment during implicit flow AuthenticationResponse

If an RP makes an auth request, and its redirect_uri param contains a hash fragment, the fragment gets lost (in implicit flow) since it gets overwritten by #id_token=...&state=... response params.

Two things need to happen:

One: preserve the original hash fragment of the redirect_uri, and add the response parameters in addition to it.

So, if the authentication request gets made with redirect_uri=https://example.com/resource#someHashFragment, the implicit flow authentication response needs to redirect to:
https://example.com/resource#someHashFragment&id_token=...&state=...&access_token=....

Note that whatever auth client is parsing the response needs to be aware of this and preserve the hash fragment while parsing (and clearing out) the response params.

Two: Since the redirect_uri of an auth request needs to be compared to the pre-registered redirect_uris array, let's make sure that the comparison is independent of hash fragments.
That is, if the RP registers redirect_uris=['https://example.com/resource'] during its dynamic registration, a subsequent redirect_uri during an auth request should be able to pass in redirect_uri=https://example.com/resource#hashFragment and have that be valid.

(Affects downstream issue nodeSolidServer/node-solid-server#571)

Fix error handling (BaseRequest.badRequest() etc)

Current behavior - returning badRequest(whatever). For example, in TokenRequest.verifyAuthorizationCode():

          return request.badRequest({
            error: 'invalid_grant',
            error_description: 'Authorization code expired'
          })

The problem with this approach is that it doesn't break out of the promise chain, and continues onto grant(), and fails on the first line of that function:

  grant (request) {
    let {grantType} = request

(Since what's being passed into grant() is not a token request, but a badRequest() promise.

Anyways, this error handling flow needs to be refactored, and needs to rely on throw, to break out of the promise chain.

Add provider.issueAccessToken() convenience method for testing

For the purposes of functional/end-to-end testing of REST endpoints (for example, using the supertest library for testing Express.js apps), the test setup will frequently require authentication via Access Tokens.

Performing the usual dynamic registration and authentication dance for each test gets to be prohibitive. Even doing it just once before the test suite is difficult, given the current state of Express.js testing tools, but even when successful, violates best practices of not relying on global state between tests.

To that end, it would be extremely helpful to have a provider.issueAccessToken(options) convenience method. (Especially useful for testing decentralized oauth Peer nodes, where the testing framework could potentially have easy access to an OP (Provider) instance.)

The options passed into it would include things like client_id, sub, scope and, optionally expiration.

Implement /logout endpoint

Implement /logout api endpoint / handler (removes the appropriate access & refresh tokens from the store, etc).

Fix authenticate/obtainConsent response workflow

Here's the current AuthenticationRequest workflow:

  static handle (req, res, provider) {
    let {host} = provider
    let request = new AuthenticationRequest(req, res, provider)

    Promise
      .resolve(request)
      .then(request.validate)
      .then(host.authenticate)
      .then(host.obtainConsent)
      .then(request.authorize)
      .catch(request.internalServerError)
  }

The problem I'm running up against is that - the last step, request.authorize, always ends up writing a redirect to the response object. Which causes an error if either the host.authenticate or the host.obtainConsent steps write anything to the response before that.
Meaning, if either the authenticate or obtainConsent steps respond with anything to the browser (which they need to), the request.authorize call results in a Can't set headers after they are sent. error.

Need to rethink how this workflow goes (at least check, in request.authorize, to see if the response has been written to, or something like that.)

Refactor Provider to specify custom URIs for API mount points

Currently, the various OIDC-related API endpoints are hardcoded in the Provider's constructor:

    data['authorization_endpoint'] = `${issuer}/authorize`
    data['token_endpoint'] = `${issuer}/token`
    data['userinfo_endpoint'] = `${issuer}/userinfo`
    data['jwks_uri'] = `${issuer}/jwks`
    data['registration_endpoint'] = `${issuer}/register`
    data['check_session_iframe'] = `${issuer}/session`
    data['end_session_endpoint'] = `${issuer}/logout`

(This also affects how they're advertised in .well-known/openid-configuration).

It would be preferable to allow a consumer app to specify which URI path to mount these endpoints on. Sort of like:

let provider = new Provider({
  issuer: 'https://example.com',
  mount: '/oidc/'
})
// -> which would lead to:
// https://example.com/oidc/authorize
// https://example.com/oidc/token
// https://example.com/oidc/userinfo
// etc

Note: This is only a refactoring of the provider's discover() functionality, not anything to do with OP express routes.

Standard README and Style Guide

To maintain a standard style across our repositories and to aid new contributors, I propose that we add EditorConfig files to our repositories and make a note of it in our READMEs.

Most editors (vim, Sublime, Atom, VSCode, etc.) have plugins for EditorConfig making it relatively easy to automate tab indentation size, UNIX line-endings and ensure that files end with a new line.

Please see the @trust/model README and .editorconfig file for the proposed configuration.

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.