Git Product home page Git Product logo

authn.io's Introduction

authn.io

A part of the solution to the NASCAR login problem.

A live version of this site and a link to a demo can be found at authn.io.

Background

A Credential Handler is an event handler for credential request and credential storage events. The Credential Handler API helps solve the Nascar Problem. The Credential Handler API enables websites to install Credential Handlers that can respond when users visit other websites that request or store credentials.

For example, a user may visit a website that wants them to login using OpenIdConnect, provide an OAuth Token, authenticate using a DID, or present some Verifiable Credentials. When these other websites use the Credential Handler API, the user is shown an in-browser selection screen with visual representations (e.g. icons and origin information) of only those Credential Handlers that they have been previously installed by the user and that are compatible with the website's request. Once the user makes a choice, the appropriate Credential Handler is loaded and a credential event is sent to it.

The Credential Handler receives the event via a Service Worker or, if the Credential Handler Polyfill is used, a simple page with no UI elements is loaded that uses the polyfill to receive and respond to the event.

The Credential Handler must respond to the event with a credential that fulfills the request. If necessary, the Credential Handler may open a window on its website's origin to allow the user to interact with its website prior to responding. This UI can be styled and shaped according to the website owner's brand using arbitrary JavaScript and HTML like any other webpage.

Credential Mediator

This software plays the Credential Mediator role described in Credential Handler API. It "polyfills" this role by running client-side code under a neutral third party origin. There is no "server" component to this software, it merely provides browser code that must be run in an independent third party origin to mimick the behavior that a behavior that implements the Credential Handler API would function.

Requirements

  • Node.js v16+
  • npm v8+

Development

The following section explains how to setup and develop the authn.io software on a local development machine.

Configuration

The options in the ./configs/authn.localhost.js file can be tuned to your environment as needed.

Setup

  • Install the dependencies

    npm install

  • Map the authn.localhost hostname to your localhost. For example, edit /etc/hosts to map authn.localhost to localhost.

Running

Run the following to start up a development server from the source directory:

node authn.localhost.js

To add more verbose debugging, use the --log-level option:

node authn.localhost.js --log-level debug

Usage

Access the server at the following URL:

Production

Full instructions for running this code in production are beyond the scope of this documentation.

A simplified startup script and systemd service file are available that could be used with appropriate modifications. Considerations must be made for scalability, robustness, TLS, and other issues.

An issue for any production environment is that that code should be bundled such that it can be served as efficient static files. After any code updates, either the production startup script, or appropriate command line flags, should be used to output the static files:

node authn.io.js bundle

A fully static site is possible but see the cookie note in lib/http.js.

authn.io's People

Contributors

dlongley avatar msporny avatar mattcollier avatar davidlehn avatar aishairzay avatar omarmalik avatar gannan08 avatar jsassassin avatar jameseaster avatar dmitrizagidulin avatar halmas94 avatar bebold avatar bigbluehat avatar joshdunndev avatar

Stargazers

shoito avatar Eduardo Chongkan avatar JiSu Bak avatar tai avatar Liam Broza avatar Matteo avatar 56 avatar Simon Brown avatar stepa.eth avatar RaisCui avatar wongzhe avatar Cab Morris avatar Joseph Werle avatar Jim Pick avatar Montana avatar  avatar Ackermann Yuriy avatar Jun Liu avatar Stefano Fadda avatar Igor Frolov avatar Paul Le Cam avatar Trevor Lazarus avatar Zach Ferland avatar Jeff Cressman avatar Christopher Wood avatar  avatar Sunny Gonnabathula avatar Sarven Capadisli avatar Jiří Špaček avatar Theodoros Ploumis avatar A. F. Dudley avatar Suvi-Tuuli Allan avatar Andrei avatar tom zhou avatar  avatar Nicola Ghirardi avatar  avatar elf Pavlik avatar Ozzie Gooen avatar Emil V avatar Chris Cornutt avatar  avatar Brad Jones avatar Melvin Carvalho avatar

Watchers

Christine Lemmer-Webber avatar Brad Jones avatar Suvi-Tuuli Allan avatar Charles E. Lehner avatar  avatar  avatar  avatar Andrew Jones avatar James Cloos avatar  avatar Ryan L. Foster avatar  avatar Adam Lake avatar  avatar Nate Otto avatar  avatar Eduardo Chongkan avatar  avatar Mark Cherbaka avatar  avatar  avatar  avatar Mandy Venables avatar

authn.io's Issues

When canceling at repo, redir to auth.io to pick another identity?

Should we add a feature to allow people to cancel a request via a repo interface but allow them to make another identity choice at auth.io and try again? Or keep it simple and cancel all the way through to the consumer (like it does presently)?

This would only apply to credential queries, as storage operations include the identity the credentials were created for.

Reorganize directory structure

The current directory structure isn't as well organized as it could be. We need to:

  • Create a lib/ directory and put all back-end code in there.
  • Refactor index.js into loginhub.dev.js and have it call code in the lib directory.
  • Create a configs/ directory and put all configs there.
  • Create a views/ directory and put index.html in there.
  • Integrate the IDP polyfill notes into the README.md

Add a specific endpoint to set the `v` cookie for Safari

Non-Safari users do not need to hit the endpoint and do not need the v cookie to enable cross-domain storage access. The cookie must not have SameSite=None set or it will not work in Safari (at least as of today's date). Therefore, we should only set this cookie when a special endpoint is hit to prevent Chrome's warning that the cookie does not have SameSite=None -- and generally because no cookies are needed for any browser other than Safari.

Update bower deps.

bedrock-angular-modal and bedrock-angular-selector have had major version releases which feature breaking changes.

We need to test with those new releases and apply fixes as needed.

Fix default icon in handler window header

The default icon for a handler (wallet) shows as a "globe" (which is the default website icon, not the default "wallet" icon) in the handler window header. The correct default icon (a "wallet" icon) shows on the wallet selection screen, but not once a wallet is selected and the handler window is shown.

Display identity name rather than email address in "select an identity" window.

When logging in or requesting credentials authorization.io is engaged and asks user to "select an identity". The identities displayed show email address rather than the identity name the user chose when creating that DID. If the user has multiple identities associated with the same email address all they see is the same email address listed over and over again. I suggest displaying the Identity name rather than the email address.

Change password-based key derivation ID to `PBKDF2`

The code currently identifies the password-based key derivation method as "PKCS5" (see: https://github.com/digitalbazaar/loginhub/blob/bf2e0d0545df632a5205ca623e324d19010f3c7e/components/main.js#L79).

PKCS#5, however, describes multiple pbkd functions, so this is unclear. We should be using PBKDF2, which refers to the specific function we use and is also the algorithm identifier used by the WebCrypto API: http://www.w3.org/TR/WebCryptoAPI/#pbkdf2

Handle Quota Exceeded more gracefully

A "Quota Exceeded" DOMException may be thrown when trying to write to local storage, for example, when a user has very little free disk space. We should handle this error or pass it on more gracefully.

running tests fails

OSX Sierra, Node v6.9.1

The server runs fine, but tests throw an error:

$ npm test
> [email protected] test ~/code/authorization.io
> node authorization.dev.js test

~/code/authorization.io/node_modules/bedrock/lib/bedrock.js:115
      throw err;
      ^

TypeError: Cannot read property 'vars' of undefined
    at Object.<anonymous> (~/code/authorization.io/configs/test.js:39:12)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at ~/code/authorization.io/authorization.dev.js:18:3
    at iterate (~/code/authorization.io/node_modules/async-node-events/lib/async-node-events.js:40:27)
2016-11-26T00:04:41.638Z - critical: worker 88648 exited with code 1
npm ERR! Test failed.  See above for more details.

JIT onboarding: Support "suggested wallet" parameter to CHAPI requests

An important component of CHAPI wallet operation will be "Just In Time" onboarding / wallet registration.
We want the user to be able to go through the following workflow:

  1. User encounters some UI (likely a button) that issues/verifies a credential or performs DIDAuth. (The user does not yet have a CHAPI wallet registered.)
  2. User clicks on the button (for example, "[ Receive Credential ]").
  3. the CHAPI UI displays "You do not have a wallet currently registered. But here is where you go to get one:"

To prevent the default wallet suggestion from having an unfair advantage, we can instead allow the requesting party (whichever app or web page is displaying the button that triggers the chapi get() or store()) to pass in one or more suggested wallet providers that the UI will suggest, in case the user does not have a wallet already.

So, here would be an example get() request:

const credentialQuery = {
  web: {
      VerifiablePresentation: {
          query: { ... },

          challenge: '3182bdea-63d9-11ea-b6de-3b7c1404d57f',

          domain: 'jobs.example.com',

          suggestedWallet: [ "chapi-demo-wallet.digitalbazaar.com", "some.other.wallet.com" ]
    }
  }
};
const webCredential = await navigator.credentials.get(credentialQuery);

In this example, the two URLs in the suggestedWallet parameter would be displayed in the "You don't have a wallet" CHAPI UI.

Add very strict CSP

authorization.io doesn't need to allow any third party content, no special objects, media, etc. We should set a very strict CSP that will cause modern browsers to enforce this.

Add a passphrase confirmation field on registration

Since the passphrase is intended to be long (for security) and since it has greater significance than just a single account on a particular service (rather it is used to remember a DID used for federated login), we should require a confirmation field to ensure people don't make simple mistakes and get frustrated later when their passphrase doesn't work.

Create a single agent/v2 route for faster polyfill loading

We currently use multiple routes for the credential agent and the credential polyfill API requires the appropriate agent URL to be provided in each API call. Also, when an API call occurs, the DOM is manipulated to add a dialog and iframe to the agent URL and then the user must wait for the iframe to load and show its UI. We have optimized this so it happens fairly quickly, but a better design can make it practically instant.

We can address all these issues with a new design:

  1. Requirement to pass agent URL to every polyfill API call.
  2. User must wait for iframe to load before agent UI can be shown.
  3. Repetitious code on different agent routes.

To address these we should instead create a single route that handles all credential agent traffic. This keeps the organization simpler and the implementation more DRY on the auth.io end. The URL for this route can be set once on polyfill inclusion (with a default to auth.io) instead of passed for each call.

The polyfill can load this single URL into a persistent iframe that is only shown when a polyfill call is made. This way websites that use the polyfill can load the agent web application early and have it be ready to receive credential API requests as they occur on the page. It would allow for immediate rendering of the UI following a user action such as a button press.

Build and run instructions

The README.md needs more information on:

  • What the software does
  • The functionality of the software
  • How you run the software in a dev environment
  • The REST API for the software

Add mocha and protractor tests

Add backend tests for:

  • successful DID document creation
  • failed DID document creation (perhaps several ways to fail)
  • successful mapping creation (eg: a "login hash", but creating a 'mapping' should be designed to be agnostic of the mapping's use)
  • failed mapping creation (perhaps several ways to fail)
  • performing a valid mapping query with a result
  • performing a valid mapping query with no result
  • performing an invalid mapping query (perhaps several ways to fail)
  • what else?

Add frontend tests for:

  • IdP registration
  • Permanent key registration
  • One-time use key registration
  • Error cases for key registration
  • Credential transfer to relying party
  • Rejected transfer to relying party (user elected to send nothing to the RP)
  • what else?

Remove session cookie

There's no need for a session cookie (it's there by default perhaps) and it should be removed.

UX problem: Wallet registration UI mimics 'Allow Notification' too closely

The wallet registration UI ("[origin] wants to: Manage credentials"):

Screen Shot 2020-05-02 at 7 26 36 PM

is too similar to the 'Allow notification UI':

Screen Shot 2020-05-18 at 9 47 21 AM

Which was probably the original intention. However, usability tests show that since users have been trained to reflexively click 'Block' to Allow notification popups, they close the 'Manage credentials' popup without looking at it. (And then are confused about why they don't have a wallet.)

Proposal:

  1. We update the registration UI to a much larger window, centered (vs its current 'tooltip' appearance).
  2. Also make re-trying registration easier (in case the user closed the window by accident).

JIT Onboarding: redirectUri parameter to CHAPI requests

(add on to the JIT Onboarding/suggestedWallet issue)

In order to support a very common use case, where users first encounter a CHAPI UI button (such as 'Receive Credential' or 'Authenticate') without having a wallet, we need to support the workflow where the user:

  1. Encounters a CHAPI get() or store() event.
  2. The UI tells them they don't have any wallets registered, and suggests some.
  3. User clicks on that wallet provider to register for a new wallet.

Since that last step is likely to take the user away from the original application they were on (especially if wallet login involves an email link), we need to provide a way to get the user back to the original requesting app (after registration).

This would be functionality similar to the OAuth2 / OIDC redirect_uri component.

Proposal:

    const credentialQuery = {
      web: {
        VerifiablePresentation: {
          query: { ... },
          challenge: '3182bdea-63d9-11ea-b6de-3b7c1404d57f',
          domain: 'jobs.example.com',
          redirectUri: 'requesting-app.example.com'
        }
      }
    };
    const webCredential = await navigator.credentials.get(credentialQuery);

Explore running a WebRTC server for connecting peers

A native app and a browser tab running CHAPI could potentially communicate via WebRTC (Native app responds to a CHAPI request) if authn.io ran a WebRTC server for establishing peer connections. Explore this.

acme-v2 dependency will stop working in October 2019

Just did a fresh install on the authn.io branch and saw this notification:

> [email protected] postinstall /home/matt/dev/bedrock-dev/authorization.io/node_modules/acme-v2
> node scripts/postinstall


================================================================================

 🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒
🍒                              🍒
🍒  Do you rely on Greenlock?   🍒
🍒               (or ACME.js)   🍒
🍒                              🍒
 🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒🍒

Hey! Let's Encrypt will STOP WORKING with Greenlock and ACME.js at the end of Oct 2019.
WITHOUT YOUR HELP we won't get the next release out in time.

If Greenlock (or ACME.js) has saved you time and money, and taken stress out of your life,
or you just love it, please reach out to return the favor today:

SAVE GREENLOCK / ACME.js:
https://indiegogo.com/at/greenlock

================================================================================

Use prefix for controllers, services, etc.

We should pick a prefix and use it for angular components. eg: DataService => lhDataService. Namespacing isn't built into angular 1.x so this is the common convention.

Customize language in fixed callout when request is for public key?

If a credentials request is made for the user's public key credential only, should we update the fixed callout at the top of the auth.io interface to indicate that? This flow is slightly different for the user than other flows in that they will not be redirected to their repo once they pick an identity, rather, picking an identity will complete the flow immediately. We might want to indicate somewhere on the UI whether or not a query requires the use of a repo or not so the user isn't surprised that they don't have a chance to cancel once selecting an identity.

Duplicate email+passphrase error not handled properly

When registering a new identity, if a duplicate email+passphrase is chosen, an error displays that says "Failed to register with the network. Try a different email address and passphrase.", however, the UI moves onto the next step showing you the information that will be sent back to your IdP, making it impossible to comply with the request to try a different email and passphrase.

Consider adding feature to enable native apps to use CHAPI

A "Use a native app" option could be presented in the CHAPI UI that would send the pending CHAPI JSON request (would need a MIME type like application/chapi+json or whatever) to a native application. The request would include a mediator URL for the native app to post the response back to. The response would then be forwarded via polling/push messaging to the user's browser that was waiting on the response from the native app -- and then sent onto the relying party like usual.

This feature (or one like it) would allow native applications to use the polyfill.

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.