Capis Login - A Declarative HTML authentication API

Most recent revision 2019-06-14. Available here.

Navigation

Introduction

The purpose of this specification is to automate the process of users signing into websites, and make the process more secure. The goal is to eliminate users having to enter passwords into forms on websites, to eliminate login forms on websites, and to replace passwords with something more secure. A list of logins can be displayed to the user (by the browser), and the user can then select the one to use. The user does not enter any data into a website form. This will allow browsers to transmit longer, more complicated, security keys to websites for the login process.

To do this, this specification defines a few new browser requirements. The browser must recognize a login "trigger" in the HTML, it must display a list of matching logins to the user, then it must encode and transmit the resulting login values (including the "password replacement") to the website. The transmission must be done using a standard protocol and a standard login value format. This specification defines one such protocol and format (CapisLogin and CLS Request). Websites are free to prefer or require other protocols, but this is dependent on browser capabilities. Browsers should support at least the base level protocol. (Note that WebAuthn is another such user authentication protocol. It can be used with or instead of CapisLogin.)

The CAPIS specification primarily defines: (1) A "Declarative HTML API". This allows an RP to define a "Service Trigger" in HTML. (2) The Client Configuration Options and RP Service Descriptor format. This allows an RP to describe RP Services and embed the descriptions in HTML. (And have the descriptions be usable by the entire HTML page.) (3) The CAPIS Service Invocation Flow browser protocol. This defines what the browser ahould do when a trigger is activated. (4) The RP Service Request to be sent to the RP. These abilities allow a website to embed a new type of "login trigger" in its HTML. (Or other types of Service Triggers.) This allows a login to be performed with a button or link, etc. Since the trigger does not have to be a form.

Example of a new Login button and login selection popup list.
Example HTML login anchor

Goals

The primary goals are:

See more details in the Design Goals.

No passwords

Passwords are insecure. They should not be given to websites, as storing passwords has proven to be too much for websites to do securely. Instead of passwords, browsers should give websites single use "login keys" to prove a user's identity. (Note: This specification combines both a "username" and User Credentials into a single JSON object, that is cryptographicaly signed, called a Proof Of Identity. A.K.A. a UserId Assertion.) However, this requires that the data submitted to websites be much longer and more complicated than passwords are, and unique for each login, so this requires the use of some type of Login Manager. (i.e. Users must not be required to type these login keys into login forms.)

Instead, users store the longer security keys in a Login Manager (a more advanced version of a Password Manager) and connect it to whatever browser they are using.

Supports digitally signing user data (i.e. form submissions)

The specification supports the digital signing of arbitrary data (i.e. form contents) by the user. This mechanism provides a general means for users to digitally sign contracts or other documents with credentials specific to an RP website. A digital signature allows the RP website to prove, internally or to other entities (the public, etc.), that the user authorized the data. This mechanism can be used to digitally sign documents, create signed statements and comments (prevents editing by a host platform. blog, twitter, etc.), perform verifiable organization voting, etc. (Note that for use outside the RP, the RP website must also have a way to prove that the Credential Verification Rules used to verify the signature were authorized by the user and active during the time when the signature was created.) (See Form Signing and CapisLogin.performUserAuth(opId, callOptions) and CapisAPI.callOptions.aUserData and CLS OpId: "signData".)

Comparison to WebAuthn

The first several goals are the same as Webauthn. Do not require users to type anything, Do not use passwords, Use some type of Login Manager. Require browsers to connect to an external Login Manager. But CAPIS adds several other requirements. (1) Eliminate login forms on websites. (2) Allow the login button in browser chrome. (login integration into the browser chrome.) (3) A Login Manager can be remote, or a program installed on another device. (Users should not be required to buy a separate physical device to store passwords or be required to carry it around with them.) (4) Allow a remote connection to an online Login Manager. (5) Must not require javascript. (Although a Javascript browser API is *also* provided, for more advanced use cases.)

See further Webauthn comparison

Why prompt the user to enter their password, if the goal is to not have them type anything. Browsers should not be required to enable Javascript for websites. Therefore, the login API shoud not require Javascript.

Overview Part 1

Two separate specifications

The login process actually involves two different specifications. (1) CAPIS and (2) CapisLogin.

CAPIS is a way for websites (i.e. RPs) to define their own services and embed Service Triggers and data values (i.e. RP Configuration Options) in HTML markup. It is a general API, and is not specific to User Authentication. It can be used to embed any type of service. It includes both new browser requirements, and new website requirements. The browser requirements include some modified HTML, and a browser protocol, called the CAPIS Service Invocation Flow. The website requirements include publishing a RP Config Document that defines the list of services (written in a service definition format), and the website must have a Service Endpoint to receive Service Requests. The new protocol can be accessed via the optional CapisControl Javascript API. The website explicitly declares, in the CAPIS HTML elements, how it wants its service to be invoked. The user's browser reads the RP Configuration Options, prompts the user appropriately (if necessary), then it sends a Service Request to the RP endpoint and awaits a Service Response. (CAPIS is known as a declarative HTML service trigger API.)

CapisLogin is a protocol that does one type of User Authentication. This is the "cls" Service Protocol Id. It can be implemented by a browser and/or by an RP Service. It is called by CAPIS when the serviceOp contains the "cls" Service Protocol Id. It defines a CLS Service Descriptor (which is an additional Client Configuration Option), and the CLS Request and CLS Response. This communication is the implementation of an RP Service Request and Response. It specifies how the browser can contact the user's Login Manager and present the login options to the user. It defines the optional CapisLogin and LoginManager Javascript APIs. It also defines the CLS Operation List. (CapisLogin is known as a declarative HTML login API.)

CAPIS can be used together with CapisLogin, or with WebAuthn or some other protocol, to perform user login. It can also perform other services hosted by the website.

Example of the new CAPIS HTML elements.
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>
...
<a href="/_capis/fallback/login.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>

CAPIS is a way to specify website services and protocol data in HTML files, without using javascript. (It's JSON.) Capis Login is a way to use CAPIS to perform user authentication. (i.e. user login.)

This specification is designed to make the process of users signing into websites easier and more secure. In order to do this, it contains both new browser requirements, and new website requirements.

It is expected that the required browser functions will be implemented natively in browsers in the future. However, a browser extension may be created that provides some of the required functionality.

This specification defines a specific User Authentication process, consisting of multiple steps, called the CAPIS Service Invocation Flow. This specification defines a browser API, that gives browsers a common set of User Authentication functionality that websites can invoke to do the collection of the User Authentication credentials. This allows websites to use the new standard, instead of having to do it themselves. (i.e. Instead of a website being required to display a login form and ask the user to enter their username and password, the website can invoke the new browser API, and the browser will do it in a standard way. The browser will collect the "username and password", or equivalent, and deliver it to the website. The browser may collect it automatically from a password manager, without user intervention.) There is a similar browser API for when a user wants to logout. Using this process lets browsers know the Login Status of a website, if it is logged in or not. The browser can display a Login Status in the UI, etc. Also, because the process has distinct steps, it allows browser extensions to hook into the process at different locations to customize the process. (i.e. To obtain the credentials from a different source, etc.)

This specification assumes that new commands and options will be presented to the user as part of the browser UI. (i.e. As a menu item displayed in the browser menu bar. Not limited to HTML elements in a web page.) The browser can have several different "login" menu items. (Perhaps displayed in a drop-down list.) The options would include (1) Display a Login Status icon, indicating if the current page is logged in or not. (2) Display the current default "Badge" (and the Login Manager that it is from). (The browser may have a setting to automatically use the default, unless the user does something to get the full login options.) (3) A list of browser commands. Including "login" and "logout" of the current web page, "logout of all" web pages, "change the default profile" that is currently being used, etc. (4) A list of what Login Managers are connected to the browser, and/or (5) options to connect to a new Login Manager.

This specification does the following, in order to automate the authentication process.

The website (or other entity) that wants to authenticate its users is referred to as the "Relying Party". (i.e. an "RP")

Specification Design Philosophy

This specification was designed to automate the User Authentication process. Its overriding design philosophy is to first streamline the existing sign-in process (remove special cases), and then automate it. Specifically, this includes:

Note that the design eliminates all of a user's custom interactions with RP websites, but it does not eliminate the user interactions with the browser. When the user clicks a special HTML anchor, the browser may pop-up a window and ask the user to make some selection. The benefit is, this user-interaction is isolated to a single party (the browser). This is much better than the user having custom interactions with every website.

Websites need users to login. This means they need proof of user identity and user presence. HOWEVER, websites should not implement their own solution to the problem. Instead, browsers should provide a standard API, and all websites should use it. Thus, instead of users being required to do data entry for EACH website, a user can prove their identity and presence ONCE, to the browser (really, to the Login Manager). The browser can then, for a limited time, be able to sign-in to multiple websites mostly automatically. (Requires a single user click. But no data entry.) Each website may have different requirements (usernames and passwords etc.), but the "Login Manager" has all of that information, and the browser has a standard way to send that data to websites. Once the Login Manager is unlocked, the browser can generate a "proof of identity" for any website that is contained in the Login Manager. And it can send the "proof of identity" to the website along with any other requirements.

Overview

CAPIS Specification brief overview

The following summarizes the CAPIS specification. (Also see Summary2.) Capis Login summary

Overview of the Authenticator

This specification requires that users store their User Logins (i.e. usernames and passwords, etc.) in a "User Authenticator". An Authenticator can be a separate physical device, or it can be software installed on a user's mobile phone, or it can be a remote service, accessed over the internet. An Authenticator must support at least one of the standard connection protocols, so that it can communicate with browsers. (i.e. via NFC, Bluetooth, WiFi, USB, or over the internet as a Web Service.) In this way, users can take their Authenticator with them, or access it remotely, and use it with any browser that supports this specification.

In order to login to websites, a user must "connect" their Authenticator to the browser once per browsing session, and prove their identity to the Authenticator. (Using a fingerprint, password, etc.) The act of connecting a browser to the user's Authenticator can be called "signing in to the browser". After connection, a user can login to websites with a single click. Without typing anything. The browser will send the Authenticator a user authentication request for the website, and the Authenticator will create a "proof-of-identity" in response. Then the browser will send the proof-of-identity to the website as part of a login CLS Request.

Overview of the CAPIS HTML elements

This specification defines a few CAPIS HTML Elements. The CAPIS Link, CAPIS Anchor, and CAPIS Form HTML elements. (The Form element is rarely used.) These elements allow RPs to embed data about RP services within HTML markup. (User authentication is one such service.) RP websites should modify their HTML pages to use the new CAPIS Link and CAPIS Anchor instead of a login form. These HTML elements have a few new HTML attributes. The attributes are rel="capis-base" and capis-config="...". The "capis-config" attribute contains a JSON-style list of name-value pairs. These are used as RP Configuration Options. RP websites can use this attribute to give the browser additional data or instructions. Such as user authentication information. Note that using the new type of HTML element does not require javascript. The RP does not have to include any javascript code in its web pages, and the browser is not required to have javascript enabled for the RP. (See CAPIS HTML Element detail.)

A CAPIS compliant HTML page MUST have a CAPIS Link HTML Element in it. The purpose is to allow the browser, in the future, to use the hidden HTML element to display the user authentication information in the browser chrome. (i.e. The RP login status and command buttons.) The items do not have to be visible in the HTML page at all. For example, the browser chrome can contain a "login" button, and a "logoutAll" button, etc.

The CAPIS HTML Elements behave differently than normal. For example, if a CAPIS Anchor is clicked, browsers that understand this specification will perform the RP Service Invocation Process. (See the CAPIS Service Invocation Flow.) (i.e. The browser will perform the CapisControl.activateTrigger.) The browser will not use the "href" attribute of the CAPIS Anchor HTML Elements. The "href" attribute is used exclusively as a "fallback" behavior. Only older browsers that do not understand CAPIS will use it. (i.e. If the browser does not understand the new attribute rel="capis-trigger".)

Example of the new CAPIS HTML elements in a page.
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>
...
<a href="/_capis/fallback/login.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>

The RP CAPIS Document

The RP must publish a special document that details the User Authentication service that the RP supports. This is the RP Config Document. It is a JSON document that describes the RP's public services. In particular, it must include the User Authentication service, and its requirements. See RP Config Document Detail.

CAPIS Service Invocation Flow Overview

In general, the act of making a RP Service call is divided into two parts, the CAPIS Service Invocation Process, and the Service behavior. (Such as Capis Login.) The CAPIS Service Invocation Flow exists so that it can be used by multiple services. It is not limited to User Authentication.

The CAPIS behavior has the following steps.

Capis Login Flow Overview

See the "Capis Login Flow Detail" for more detail.

When a "user authentication serviceOp" is started, the browser will try to communicate with the active Login Manager. If there is not an active connection to a Login Manager, then the browser will prompt the user to connect to (or login to) a Login Manager. A connection to a Login Manager can expire or otherwise become invalid. If the user has been inactive for some amount of time, or if the RP requests it, then the Login Manager can require that the user re-authenticate himself (to the Login Manager), before the Login Manager will generate the proof-of-identity. (This optional RP request is one of the primary actions, and is called "proveUserPresence".)

Differences between CLS and WebAuthn

The Capis Login specification defines a login process and HTML integration for the browser. CAPIS may use the WebAuthn specification as one of the supported login implementations. The differences between CAPIS and WebAuthn are:

Specification Design Goals

Primary Design Goals

The primary design goals are: The primary goals of this specification are:
  1. Automate user authentication. Allow users to login to websites with a single click.
  2. Users should be able to sign into websites with a few clicks. (No typing. No data entry.)
  3. Eliminate the need for users to remember multiple passwords.
  4. Allow users to "use any browser" and "take their password device, etc. with them".
  5. Standardize the use of better security practices in browsers and websites.
    i.e. Prevent websites from storing raw passwords, and thereby eliminate the possibility of passwords being compromised through website breaches.
  6. Prevent browsers from sending raw passwords to websites. Instead, it uses public keys or hashes. This prevents websites from storing raw passwords.
  1. Users must be able to store their login credentials in a "Login Manager" external to the browser. (A Login Manager can be an online service, or a physical device the user carries, etc.)
  2. Users must be able to connect to their Login Manager with any browser when doing sign-in.
  3. Browsers must be able to connect to an external "Login Manager". This should not require installing a browser extension.
  4. The RP websites must be able to inform browsers about its User Authentication requirements. Including any custom settings.
  5. Browsers must be able to get the User Authentication requirements for the RP website.
  6. Browsers must be able to create and send a proper "login request" to the RP website. Including the sign-in information required by the website. (Using the required format and protocol.)
  7. Browsers must know the "Login Status" at each website. (This means that a login and logout CLS Response MUST be sent from the RP website and parsed by the browser.)
  8. Browsers must be aware of each User Authentication CLS Request, (i.e. login, logout, etc.) and each corresponding CLS Response from the RP website.
  9. Browsers must provide a standard "login prompt" for RP websites to use.
  10. The "login prompt" should not be an HTML form. Login forms should be eliminated. (Could use a special HTML element, etc.)
  11. The "login prompt" must be specific and exclusive. The browser MUST not have to guess which HTML elements and/or forms are used for authentication. It must not have to guess what conditions will trigger the login prompt.
    If the "login prompt" is part of the HTML page, then there must be a standard way for an RP to mark which HTML elements it uses to trigger the login process. (i.e. the "login prompt".) (It must not be like the current way things are done, using a regular, unmarked, HTML form to submit the username and password.)
  12. Activation of the special "login prompt" must cause the browser's internal login function to execute.
  13. The "login prompt" should work without javascript. Therefore, it should probably be a special HTML element. Dedicated to doing login / User Authentication.
  14. Browsers should have a "login function" that causes a "login request" to be sent to the RP website.

Secondary Design Goals

Secondary goals are:
  1. Eliminate sign-in forms on websites. Replace them with links. (Websites should never prompt users to enter sign-in data.)
  2. Work without requiring any Javascript
  3. Support multiple "opId" values. (Such as "login", "logout", and "proveUserPresence")
  4. Support Multi-factor authentication
  5. Browsers should provide a standard way for websites to ask for confirmation of user presence. After sign-in. (i.e. To confirm the user is still there.)
  6. Browsers should provide a "global logout" button. An easy way for a user to "sign-out from the browser".
    One button that will cause the browser to logout from ALL websites that use the credentials of the Login Manager. The browser MUST send a "user has signed-out" notification to all websites that are logged in using the user's credentials.
  7. Be extensible.
About the RP Service Invocation Process
  • The process must not require the use of javascript on RP websites.
  • The process must be customizable. So that RP websites can adjust the process with their own customizations. (different URIs. different protocols, different formats)
  • The process must be extensible. So that it can be automated and extended in the future.
  • An RP website must be able to "declare support" for the standard.
  • The process must have discrete "steps", so that the browser (and browser extensions) can "hook into" or customize the login process.
  • An RP must be able to have confidence that the browser (or some "User Authentication Device") has confirmed the presence of the user. Not just the presence of a device. (Confirm the user by some physical or mental characteristic. Such as having them enter a password into the browser window.)
  • It must be extremely easy for websites to implement. (Eliminate the need for custom scripting.)

User Authenticator detail

A User Authenticator provides cryptographic proof of a user's identity. That is, it creates a proof-of-identity for an RP. It creates this proof from the User Login's credentials. (i.e. The credential secrets. Like a password or private key, etc.)

A Login Manager is a container that stores all of a user's login credentials. (i.e. It stores all the usernames and "Credential Secrets" such as passwords, private keys, etc.) A "Login Manager" is an advanced form of a "Password Manager". It has a different name because it can store other types of login credentials besides passwords. (Such as public/private key pairs, etc.)

An Authenticator needs access to the user's Login credentials, such as passwords, and private keys, to create a proof-of-identity from them. In other words, an Authenticator *requires the use of* a LoginManager. It needs access to the credentials, but it doesn't need to store the credentials itself. It is an additional capability beyond that of a LoginManager. But this functionality is simple enough, that most Login Managers should not have a problem supporting it.

When looking at the LoginManager API, there are 3 required Authenticator functions. findUserLogins, createUserLogin, buildProofForRp. (They usually accept the "rpClientData" argument.)

An Authenticator has a few required capabilities. Primarily, it can use cryptography to generate a "proof-of-identity" for an RP. It creates this proof from the User Login's credentials. (i.e. The credential secrets. Like a password or private key, etc.) The proof-of-identity is a type of cryptographic digital signature. It proves that the Authenticator knows the credential "secret", without revealing the secret to the RP.

Second, an Authenticator must support at least one of the standard connection protocols, so that a browser can communicate with it. (i.e. via NFC, Bluetooth, WiFi, USB, or over the internet as a Web Service.) Third, it must support a specific software API. This API allows a browser to ask it to create a proof-of-identity for an RP.

A "proof-of-identity" proves who the user is, without revealing the user's password. The "proof-of-identity" is given to the RP website as part of the login request. The proof-of-identity is cryptographically signed. It also includes a timestamp, and the "challenge" from the website. (A "challenge" is a "cryptographic nonce" value.) In this way, the website can verify that the proof was newly created, and that it uses the correct "challenge" value. (i.e. the one that the RP created.) Because of this, the proof-of-identity will only work for one website. (The one that created the "challenge" value.) Also, a previous proof-of-identity will not work. This specification uses a JSON Web Signature as the proof.

(An Authenticator can contain multiple "accounts", with each account storing the User Logins for a separate person. Although this condition is rare, it is supported.)

RP Requirements

In order to use the new login methods, RP websites must do the following.
  1. Publish a RP Config Document. (This details what user authentication the RP supports.)
  2. Set up an "Endpoint". A URL to receive and process the "CLS Requests" from browsers.
    (The endpoint is published in the RP Config Document.)
  3. Store Credential Verification Rules for users. (i.e. public keys, password hashes, etc.) An RP must be able to verify the types of user authentication that it lists in the CAPIS Document.
  4. Create "fallback" pages for older browsers. Copy or move existing login forms, etc. (i.e. the login form, the password reset form, etc.)
  5. Change its HTML pages to include a few CAPIS HTML Elements. (i.e. A link and an anchor.)
    One of these new attributes must be a "challenge" and contain a very long, unique integer value. (This is a cryptographic nonce value.)
  6. An RP MUST have distinct account ids and user ids, and map between the two. (This is common practice.)

    The mapping may be "one-to-one", "one-to-many" or "many-to-many". A mapping is necessary because, at the very least, a user's UserId can change. (A UserId can become invalidated, compromised, retired, etc.) A "one-to-many" mapping is recommended, as it enables more features. It allows the RP to support Account Sharing. (This allows a user to safely share their account with other people.)

See RP requirements detail.

Browser Requirements

It is anticipated that browsers will be updated to support these requirements natively. But there will also be javascript libraries that will enable it in older browsers.
  1. Ability to perform the CAPIS Service Invocation Flow.
  2. Ability to connect with a Login Manager. (i.e. User Authenticator. An external device, software or Web Service.)
  3. Ability to read (and execute) a few new HTML elements.
  4. Ability to retrieve the RP Config Document from the RP.
  5. Ability to show a pop up dialog to the user, that asks them to pick from a list of UserLogin.
  6. Ability to send the service request to the RP.
  7. Ability to generate a QR code from the RP endpoint URL and nonce, and show that to the user. If the user asks for it. "https://domainName/path/file.json?ch=nA8rh3tfe83h37C9B2O5Zw4Yn2pV7M"
    Note: In order to allow out-of-band login, the server must be specially configured. It must index the sessions by the nonce value.
  8. For the Authenticator -- Ability to generate passwords or public keys, etc. for user credentials.
  9. For the Authenticator - Ability to generate a proof-of-identity.

Benefits

Benefits of this specification

It modifies the login process in the following ways.

Main points
Example of a special HTML anchor:
<a href="/_capis/fallback/login.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/login" '>Login</a>

More Benefits 2

As corollaries, or additional support to the above, this specification also:

The RP Service Invocation Process will cause the browser to retrieve the CAPIS Document (via HTTPS), then display to the user a list of UserLogins that match the RP Service requirements. The user can choose the UserLogin of their choice, or choose to create a new login. New logins can be created automatically. (new, secure, public/private key pairs are generated.)

The browser will send the website an "Authentication Service Request". The request includes a login proof, and is signed by the appropriate private keys. The request is a JSON Web Signature (JWS). The JWS can also contain credential attestation, for any newly generated public keys / credentials. (If attestation is a requirement of the RP website.)

The list of newly created formats include:

Overview Old

This specification adds behavior to browsers and RPs (e.g. websites) to let users sign in with a few clicks. It eliminates manual sign-in forms on websites.

Specification Summary

This specification does the following:

  1. Defines the CAPIS Service Invocation Flow.
  2. Defines a few new HTML elements for the "RP Service Invocation Process". These are used by an RP to augment a few HTML elements. These attributes: 1. identify which HTML elements are used to do sign-in, and 2. hold RP Configuration Options. (This vastly simplifies the login process. The browser doesn't have to guess which HTML elements are used to do sign-in. i.e. Which forms submit a username and password, etc. It doesn't have to inspect form inputs or examine javascript for clues, etc.)
  3. It defines a standard way for an RP to declare what RP Services it supports. The services are published in an "RP Config Document". The service definitions include the "RP service endpoints" and communication protocols used.
  4. It defines a standard format for the CLS Requests that a browser sends to the RP. This includes a requested serviceOp, and a "proof of identity", which includes a UserId and a set of user credentials. The credentials can be a mix of different types. (The ability to send multiple credentials, of different types, allows an RP to support Multiple Credential Authentication and multi-factor authentication.)
  5. It defines a standard multi-step process for browsers to follow. It starts when an "CAPIS HTML Element" is clicked on by the user.
  6. CapisLogin. The API defines several functions, including "login", "logout", "proveUserPresence", and "setActiveCredentials" (i.e. "change password").
    This provides an easy, standard way for browser extensions, etc. to hook into the RP Service Invocation Process. Thus, the user experience can be customized easily. It can modify or preempt certain actions, etc. For example, during user authentication, the browser can present additional options, such as allowing the user to connect to an "User Authentication Device" or to an online "Login Manager". It can use either of these sources to create proof of the user and their login credentials.
  7. It defines a standard way for an RP to declare a custom behavior for an HTML element. The CAPIS Trigger Behavior will cause the contained serviceOp property to be performed. (The serviceOp value should contain a opId that is one of the CLS Operation List. i.e. "login", "logout", "proveUserPresence", etc.) This explicitly tells the browser what the purpose of the element is. (i.e. which serviceOp to perform.) This allows the browser to add custom behavior based on the serviceOp. (It may color anchors that have a "cls/login" serviceOp differently. etc.)
  8. It defines an optional Javascript API that browsers can implement.

Term Definitions

Relying Party (RP)
An entity that wants to authenticate a user. i.e. The system or service being logged into. For example, when a user logs into a website, the website is the relying party. (An RP "relies" on an authentication system to verify the identity of the user.)
Relying Party Identifier (rpId)
A unique identifier for a Relying Party entity. It is based on the RP's "domain name". Example: "login.example.com" It is not a URL, even though it may look like one. It MUST not include a scheme, port or username. By default, the rpId is created from the RP's origin. However, a Relying Party can override this behavior, and set the rpId in the RP Config Document or Client Configuration Options. An rpId MAY include an optional path. This lets user accounts at an RP maintain their own client logins if desired. (See "serviceDesc.baseSapId", "serviceDesc.baseSapId".)
User Authentication Service Application Id (sapId)
A unique identifier for a User Authentication Service Application. (UserAuth ServiceApp) The abbreviation comes from "user auth Service Application". (It may be called a database or system, rather than an "application".) A sapId is similar to a domain name, however it may also contain additional parts, such as a GUID. Example: "login.example.com". The sapId is the id under which a Login Manager stores the User Logins for an RP, or organization. An RP tells the browser which Service Application to use by setting the "serviceDesc.baseSapId" property. Usually, each RP creates its own sapId, and only allows itself to access User Logins that use it. However, a larger organization may set up multiple RPs to use the same sapId. (Known as SSO. Single Sign On.) Access to a sapId is validated, so that only an "authorized" RP can access User Logins that use that sapId.
Foreign RP
Any RP that is not creator of the UserLogin (and the associated User Credentials). See allowedScope.
User Identifier (UserId, UserId)
A string of characters that uniquely identifies a user to an RP. It is almost the same as a "username" (as in a "username and password"), except that it does not have to resemble a name. Because it is not meant to be displayed to, or remembered by, users. It is usually specified by the RP, not chosen by the user. (See UserLogin Creation Methods.) The two main types of UserId are "Single-site UserId" and "Locked Id". CIQ is a format for how identifiers should be written. Also see CLS Response assignedUserId.
Examples: "little_bo_peep12345", "p93w43m7", "ciq:C:B1:1:M8h2Dz0Wyv_lViQ4Nr0J"
Identifier Lock
A set of requirements or an Unlock Verification Method that is referenced within a "locked identifier". Such as a Locked Id. This functions as a type of "user authorization test". Only users that are authorized to use the identifier can unlock it.

A lock can be designed for either "private access" or "public verification". In the first case, the method can "grant access" to a restricted resource to the entities that can unlock the identifier. This will give those entities secret information, etc. In the second case, the method can be used by an unknown entity (i.e. a third-party, or "the public") to verify if a user can unlock the identifier. A Locked Id is used for public verification. Third parties can challenge a user, and then verify that the user's response (some documents given to them by the user) contains the challenge value, and will unlock the identifier. The response is verified with the Unlock Verification Method. If the response satisfies the test, then the user is authorized to use the identifier.

The identifier must be in a standard, recognizable format, so that the type of lock used in the identifier can be determined by the public. Each type of lock has an associated Unlock Verification Method. A format may either use only one type of lock, or it may contain meta information that specifies what lock type it uses. (i.e. It can contain some kind of type_id or standard_id, etc.) For example, the CIQ format contains a standard_id that specifies the standard that the the identifier follows. The standard_id also defines the type of the lock used in the identifier. (i.e. The type_id specifies the type of requirement, service or Unlock Verification Method contained in the identifier.) For example, an email address is in a specific format and has just one type of unlock method (i.e. sending email). Other standards, such as "webfinger", do not use a format that is distinctive enough. IDs using such standards must also specify the "standard_id". (e.g. The ID must contain the string "webfinger". Like "webfinger:1:carol@example.com") Such standards commonly define a particular URL to use at the contained domain name, and any required arguments. (e.g. url="example.com/.well-known/webfinger?resource=acct%3Acarol%40example.com") The URL is used to retrieve a document that contains the Unlock Verification Method.

Some other notes. A lock algorithm may include a reference to an online location, a document or a service, etc. (e.g. A Federated UserId commonly requires a Backer VM.) The document can contain public keys, or the service can issue a certificate, etc. that can be used to verify the user. When a locked identifier is used as a public identifier, an RP must not register a Locked Id to any of its users, unless the user can unlock the ID.)

See Identifier Use Requirements.
Identifier Lock Type
The type of Identifier Lock used in a Locked Identifier. The lock type uniquely identifies the Identifier Unlock Verification Method. Note that multiple "lock types" may use the same Identifier Unlock Verification Method. Also note that multiple locks may be created that use the same lock type. For example: a lock type of a base64url encoded public key. (i.e. a self-contained lock.) (Specifically, an Identifier Lock may depend on the contents of the payload. For these cases, the Identifier Unlock Verification Method will assemble or otherwise determine the actual lock requirements.)
Identifier Unlock Verification Method
An algorithm by which a "verifier" (i.e. a third party, an RP, etc.) can verify if an entity (i.e. a user) can unlock a Locked Id. It is known as an "IUV Method". It usually verifies if some documents created by the user are valid, and pass the lock's test or requirements. The documents should also pass the test presented by the verifier. (An alternate method is that the user provide a secret, such as a password, to the IUV Method to prove their authorization. However, this method may reveal the secret to the verifier.) Each type of lock will have its own IUV Method. That is, a way of proving if the user meets the lock requirements that are referenced from within the identifier. This verifies if the user is authorized to use the identifier.

In order to work, the verifier generally requires two things. (1) The IUV Method for the type of lock. (2) All documents or services required by the IUV Method. Note that the IUV Method of the identifier is generally determined by the "type" of the identifier lock. The requirement to determine the "type" of the identifier lock may require that the identifier be in a standard, recognizable format. The IUV Method is commonly defined by the "standards organization" that defined the type of lock.

In some cases the IUV Method may require extra documents. Such as for a Federated UserId. In this case, the verifier may need to verify that the backer documents were issued by the backer. So it may need to get the public keys for the Backer via a Backer VM.

The "type" of the Locked Identifier determines how the identifier is put together, and what pieces it is composed of. Some pieces can be: (1) the type of lock used by the identifier, (2) the IUV Method, and (3) the "triggerId". The triggerId allows the same lock to be used by multiple users. The triggerId specifies the user of the lock. It is one of the arguments given to the IUV Method.

In the CIQ format, the combination of the "namespace" and "lockType" specifies the "type" of the Locked Identifier. Use this to determine the IUV Method. (Ex: "C:F1:3" specifies a Federated UV Method.)

Examples:
  • "ciq:C:B1:1:M8h2Dz0Wyv_lViQ4Nr0TN5BfJ" // Type "C:B1:1" is a base64url encoded JWK public key.
  • "ciq:C:F3:1:1234567890:example.com" // Type "C:F3:1" contains a decimal integer and domain name.
Identifier Unlock Proof
A document or a service result that can prove to a third-party that an entity (i.e. a user) can "unlock" the identifier. That is, the user meets the requirements of the identifier. This is also known as the user "Unlocking the Identifier". The proof must be verifiable to the third party. The document can be verified through a Identifier Unlock Verification Method. For a Locked Id, this proves the user can pass the user authorization test, and is therefore authorized to use the identifier.
Register an identifier with an RP
Having an RP associate a user with an identifier. This may be the same as User Login creation. Or the RP may change the UserId of the user. The RP "assigns" the identifier to the user, or allows the user to choose their own identifier. If the identifier is a Locked Id, then the RP must not allow it, unless the user can unlock the ID. Because that would allow someone who does not own the Multi-site UserId to create a login using the UserId. (This is a security risk). A "locked" ID is RESERVED. See UserId registration.
User Login (See LoginItem)
The data needed for a user to login to an RP. (i.e. To authenticate a user to an RP.) This generally consists of (1) The RP id. (2) A UserId. (3) Some set of "secrets" known only to the user. (i.e. Credential Sources. Such as private keys or passwords.) (4) A matching set of "user secret verification data" (i.e. Credential Verification Rules), to be stored by the RP. (This proviedes a way for the RP to verify that the user has the secrets.) (Note: A "username and password" is a simple case of a User Login, where the password serves as both the "secret" and the "user secret verification data".) Stored User Login data may also contain some additonal information for administration purposes. (Such as a lipId.) See User Login Detail.
LoginItem
Any of the items inside a Login Manager, that are stored in relation to a User Login. Typically these are the stored User Login data, and Badges. A Login Manager and RP may contain multiple LoginItems, with the two storing slightly different informaiton. The RP does not need to store the RP id (for itself). The RP does need to store the "user secret verification data" (i.e. Credential Verification Rules).
LoginItem Permanent ID (i.e. a "lipId")
A unique identifier assigned to each LoginItem in a Login Manager. Example: "ug34". The lipId does not change if the UserId is changed, or if the UserLogin is moved to a different Badge. Both UserLogins and Badges have a lipId.
Leaky User Login
A User Login that reveals some of its credential source secrets through bad Credential Verification Rules. (i.e. It has at least one "leaky" Credential Verification Rule.) A "username and password" is an example. The RP typically stores the password in order to validate login attempts. However, having the RP store the (unencrypted) password is unsafe. Anyone with access to the RP can copy the secret and can impersonate the user.
Single-site User Identifier
A type of UserId that only identifies a user at a single RP. At a different RP, the same UserId can be registered to a different user. It is the opposite of a Locked Id. A Single-site UserId can be written in CIQ format using one of the "C:A:" types.
Examples: "little_bo_peep12345" or "ciq:C:A:3:X0s5eA:Aq"
Multi-site User Identifier
A Locked Identifier used to identify a single user to multiple RP. (i.e. It is a type of user identifier. UserId) Multi-site UserIds are "foreign" to every RP. (Other than its Backer. If it has one.) It is the opposite of a Single-site User Identifier. See Multi-Site UserId detail for more information.
Locked Identifier (Locked Id, LID)
A type of identifier that references or contains some sort of "lock", test, or "verification method". The lock provides a way for an entity (i.e. a user) to prove that they are authorized to use, or have control of, the identifier. Systems SHOULD not allow a Locked ID to be used unless the agent can prove it can unlock the ID.
Correct use of Locked Ids require compliant behavior from systems. For example, an RP must not register a Locked Id to any of its users, unless the user can prove that they can unlock the ID. Because of this requirement, Locked Ids MUST be distinguishable from other types of identifier used by the system, and the Unlock Verification Method used by the Locked Id must be discernable. The system must be able to (1) tell if an identifier is "locked", and (2) verify if an agent can unlock it. Using the CIQ format is one way to meet these requirements. Locked Identifiers are either Hosted or Self-contained. If a Locked Identifier is used to identify a single user to multiple RP, it is a Multi-site UserId.

There must be a way for verifiers (i.e. third-parties, RP, etc.) to be able to verify if an entity (i.e. a user) is authorized to use, or has control of, the identifier. (i.e. If the user can "unlock the ID".) If the Locked Identifier is hosted, then the host must provide this "unlock verification". This generally is done in one of four ways. First, the host can perform the verification itself. It accepts some sort of "documents or user supplied information", such as a password, and returns some sort of success or error value. Second, the host can receive a secret message. If the user can access the secret, then they have proved access. Third, the verifier can be given the "verification method". Then the verifier can verify the documents itself. The "verification method" can be some sort of algorithm or public keys, etc. Fourth, the verifier can be given the "encryption key". The verifier can then encrypt a secret message. If the user can decrypt the message, then they have proved access. The host can limit any of these methods to only certain verifiers. If the identifier is used as a Federated UserId, then this service may be known as an Identity Provider. Or the host can provide something different.

Examples:
  • "ciq:C:B1:1:M8h2Dz0Wyv_lViQ4Nr0TN5BfJ" // Type "C:B1:1" is a base64url encoded JWK public key.
  • "ciq:C:F3:1:1234567890:example.com" // Type "C:F3:1" contains a decimal integer and domain name.
Self-contained Locked Identifier
A type of Locked Id that contains its lock inside itself, internal to the identifier. For example, the lock can be an encoded public key. In this case, the public key can be used as the "verification method", so the verifier can check itself that the user can unlock the ID. These types of Locked Id do not have a "host". They are written in CIQ format using one of the "C:B1:" types.
Example: "ciq:C:B1:1:M8h2Dz0Wyv_lViQ4Nr0TN5BfJ" // Type "C:B1:1" is a base64url encoded JWK public key.
Hosted Locked Identifier
A type of Locked Id that relies on a "host" to contain or implement the lock associated with the identifier. Because the lock is hosted, the identifier must somehow be associated with the host. However, the identifier does not necessarily have to contain the host id. The identification system may keep or provide the host ID separate from the Locked Id. If the identifier contains the host ID itself, then it is a Backed Identifier. Where the "host" is the Backer Organization. A Hosted Locked Identifier that is used as a user identifier is a Federated UserId. An email address is an example, it references a "user account" at a domain name (i.e. the host). The "lock" or test is if the user can receive email at the address.
Examples of Locked Identifiers. When in CIQ format, it should probably use one of the "C:F1:" or "C:F3:" types.
  • "little_bo_peep12345" // An identifer without a host id. (Not recommended as a Locked Identifier.)
  • "user123@example.com" // An email address. The domain name is the host id.
  • "ciq:C:F1:1:1234567890:ACMA_org" // Type "C:F1:1" contains a decimal integer and a SimpleBackerId.
  • "ciq:C:F3:1:1234567890:example.com" // Type "C:F3:1" contains a decimal integer and domain name.
Backed Identifier
An identifier that contains at least two parts, a Backer ID and a "registration id". The Backer Id identifies the Backer Organization that issued the ID, and the "registration id" identifies a particular resource, account, user, or transaction, etc. at the backer organization. An email address is an example. Also known as a "third-party" identifier.
Example: "user123@example.com" // An email address. The domain name is the host id.
Backer Organization
An organization that creates Backed Identifiers. Every Backer Organization is identified by a unique ID, called a Backer ID. Every Backed Identifier contains the ID of the backer organization that created it. A domain name is an example of a Backer ID. An email address is an example of a Backed Identifier. (someone@example.com)
Backer Document Verification Method
A document or service provided by a Backer or a delegated third-party, such as a Identity Provider, that can be used to verify documents were issued by the Backer. The document or service may also provide public keys, which can be used to verify signed documents were issued by the Backer.
Backer Id
The ID of the Backer Organization, which creates Backed Identifiers. Every Backed Identifier contains the ID of the backer organization that created it. A domain name is an example of a Backer ID. An email address is an example of a Backed Identifier. (someone@example.com)
A Backer ID must be assigned by a standard system, to ensure that all Backer Ids are unique. A Backer ID may be a domain name or something similar. It may be a permanent SimpleBackerId, assigned by a different standard. All Backed Identifiers issued by a Backer must be in a standard format. This is so that RPs that receive one of the Backed Identifiers, can recognize the item as a Backed Identifier, and extract the Backer ID from it.
Simple Backer Id
A permanent identifier for a Backer Organization, assigned by a standards body. It is a type of Backer Id that does not use a domain name. (This is a way to create Backer Ids, and therefore Backed Identifiers, that do not use domain names, and therefore do not have the problems of domain names. It allows the IDs to be permanent, etc.) The standards body should publish a single document that contains all the Backer Ids that it has assigned. The Backer Ids in the document are permanent and cannot be changed. (New entries can be added.) The document should also contain the Federated UV Method for each Backer.
Federated User Identifier
A unique identifier, used to represent an external entity, or "user". All Federated User Identifiers have a "provider". The "Federated Identity Provider" is a single organization that is responsible for authenticating a user to members of the federation. Therefore, each "Federated User Identifier" must be "linked" or associated with its "provider".

A Federated User Identifer is a type of Locked Id that uses an Identity Provider to implement its lock. (i.e. To meet the Locked Id requirements.) The identifier may or may not be a type of Backed Identifier. (i.e. The identifier may or may not contain a provider ID.) The provider may be provided separately. If the Federated User Identifier contains a unique ID specifying the provider, then it is a type of Backed Identifier. Where the "provider" is the Backer Organization. The Identity Provider may be the same as the Backer Organization.

In order to work, the verifier generally requires two things. (1) The IUV Method for the type of lock. (i.e. The Federated UV Method.) (2) All documents or services required by the IUV Method. Note that the IUV Method of the identifier is generally determined by the "type" of the identifier lock. The requirement to determine the "type" of the identifier lock may require that the identifier be in a standard, recognizable format. The IUV Method is commonly defined by the "standards organization" that defined the type of lock.

In some cases the IUV Method may require extra documents. Such as for a Federated UserId. In this case, the verifier may need to verify that the backer documents were issued by the backer. So it may need to get the public keys for the Backer via a Backer VM. See Federated UserId detail.

The "type" of the Locked Identifier determines how the identifier is put together, and what pieces it is composed of. Some pieces can be: (1) the type of lock used by the identifier, (2) the IUV Method, and (3) the "triggerId". The triggerId allows the same lock to be used by multiple users. The triggerId specifies the user of the lock. It is one of the arguments given to the IUV Method. The triggerId is the "registration id" specifying the user to the provider. (4) The provider.

In the CIQ format, the combination of the "namespace" and "lockType" specifies the "type" of the Locked Identifier. Use this to determine the IUV Method. (Ex: "C:F1:3" specifies a Federated UV Method.)

Examples:
  • "user123@example.com" // An email address. The domain name is the host id.
  • "ciq:C:F1:1:1234567890:ACMA_org" // Type "C:F1:1" contains a decimal integer and a SimpleBackerId.
  • "ciq:C:F3:1:1234567890:example.com" // Type "C:F3:1" contains a decimal integer and domain name.
Federated UserId detail
A Federated User Id is a type of Locked Id that uses a Backer Organization to implement its lock. It is a type of Backed Identifier.

In order to work, the verifier generally requires three things. (1) The "type" of the identifier. (2) The IUV Method for the type of lock. (i.e. The Federated UV Method.) (3) All documents or services required by the IUV Method. The requirement to determine the "type" of the identifier may require that the identifier be in a standard, recognizable format. The IUV Method is commonly defined by the "standards organization" that defined the type of lock. In some cases the IUV Method may require extra documents. Such as for a Federated UserId. In this case, the verifier may need to verify that the backer documents were issued by the backer. So it may need to get the public keys for the Backer via a Backer VM. See Federated UserId detail.

The Federated UV Method implements the Identifier Unlock Verification Method required by a Locked Id. It is the standard way for the RP to verify if the user currently connected to it is actually actually authorized to use the claimed UserId.

A Federated UV Method commonly involves validating documents issued by a third party. The party is either the Backer, or an Identity Provider working for the Backer, etc. (The document may be some sort of UserId certificate, etc.) Therefore, a Federated UV Method commonly requires the use of a Backer VM to validate the documents. The Backer VM must be "authorized" by the Backer but it may be provided by a separate entity. For example, a combination User Authentication Service may provide user verification for Federated UserIds from several different Backers.

In order to use the Backer VM, it must be "findable" by all RPs. All RPs must know the URL and any other information needed to use the Backer VM. Typically the method is published in one of three ways. (1) The Backer domain name publishes the information. (2) The standards organization for the type of UserId publishes the information. (3) The UserId type and method are well known. (e.g. Like an email address.)

All three options require the UserIds of that type to be in a recognizable format. The UserIds must either contain an explicit "type ID" for the type of Federated UserId they are, or they must be in a format where their "type ID" can be inferred. (i.e. An email address format will cause the email address "type ID" to be used. etc.) The CIQ format makes this easy as it contains an explicit "type ID" for the UserId. In the CIQ format, the combination of the "namespace" and "lockType" specify the Federated UV Method. (Ex: "C:F1:3")

In order to login to an RP using a Federated User Id, a few things are needed. First, the RP must support that type of User_id.

During a login attempt, an RP will extract the "type ID" and the "Backer Id" from inside a Federated UserId. (Note that the "type ID" may be inferred from the format of the UserId. For example, an email address format will use an email address "type ID".) Then the RP must execute the Federated UV Method for the type ID, and have it validate the documents provided by the user during the login attempt. The "UV Method" algorithm may have a step that requires using the Backer VM for the Backer of the ID. If this is required, then the Federated UV Method will specify how the Backer VM must be "found".

For example, an email address is a type of Federated UserId, but it may not actually be "working", as the Federated UV Method to use for any email address EXISTS, but is not desireable. Sending the user an email may not work reliably, and it also requires user interaction. (The user must click on a link in ther email.) There is no standard way for an RP to find what Backer VM the domain name in the email address supports. (1) Not all domain names are listed in a standard (global) index of User Authentication Services, and (2) there is no standard way for an RP to query the domain name in the email address to find what Backer VM it supports.)

Any website may turn its user accounts into Federated UserIds. It only needs to provide (and publish) a Backer VM that RPs can use to prove if a user is registered at the website. (i.e. owns a UserId at the website.)

If RPs allow Federated UserIds to login, it is recommended that they ALSO require Credential Verification Rules (such as passwords or public keys) IN ADDITION TO the proof from the Federated UserId's Federated UV Method. This prevents existing accounts at RPs from being hijacked if a Federated UserId is compromised. Only during user signup (i.e. account creation at an RP) SHOULD the proof from the Federated UV Method be used by itself. This is used to ensure that the requested Federated UserId is actually owned by the new user.

Typically, a Federated UserId is written in CIQ format, as the CIQ "type" will clearly denote how the Federated UV Method issues identity proof.

Federated Unlock Verification Method
An algorithm by which an RP can verify if a user has unlocked a Federated UserId. That is, if the user meets the lock requirements that are referenced from within the identifier. The method usually verifies if some documents presented by the user are valid. (This method is a Federated UserId implementation of the Identifier Unlock Verification Method.)

The Federated IUV Method always involves a third party, or documents from a third party. (i.e. The Backer, or an Identity Provider, etc.) (Maybe the IdP works for all the UserIds that use a certain Backer, etc.) The Method may be some sort of "unlockable access" or UserId certificate, etc.

The user typically must know some sort of "secret" belonging to the UserId. (A password, cryptographic signature, etc.) With a Federated UserId, the user does not submit the proof to the RP. Instead, he submits it, and the claimed UserId, to a third party. The Backer or an Identity Provider that works for the type of UserId, etc. The service will examine the proof and, if valid, will create some kind of document that states that the user is valid. This document is typically some kind of digitally signed statement, such as a UserId certificate. The document is a part of the proof of identity. (It may consist of other documents as well.) The document is delivered to the browser, which sends it to the RP. The RP then has to validate the document.

The RP must trust the third-party. Or it will not matter what documents the RP receives from the third-party.

Typically, a service will only support a very limited set of identifiers. (For example, identifiers that contain the "Backer Id" of only one or two particular Backers.)

In order for RP to support Federated UserId, the RP must be able to execute the Federated UV Method for that type of UserId. Typically the method requires a Backer VM. The Backer VM is published in one of three ways. (1) The Backer domain name hosts a standard document or lookup service. (2) A standards organization published the standard document or lookup service. Or (3) The account type is well known. (e.g. Like an email address.) All three options require the "type" of the Federated UserId. The UserId must either contain an explicit "type ID" for the type of Federated UserId it is, or it must be in a format where the "type ID" can be inferred. (e.g. Like an email address.)

In the CIQ format, the combination of the "namespace" and "lockType" specifies what Identifier Unlock Verification Method to use. This specifies the Federated UV Method. (Ex: "C:F1:3")

Another way of getting the type is if the Backer Id is written in a format of a SimpleBackerId Standards Organization.

timestamp-identifier
A combination of a timestamp and a small integer, both encoded in base64url. Together, it provides a unique identifier, even if there are multiple identifiers created in the same millisecond. It is composed of a Unix timestamp integer, encoded in base64url, and a small integer, also encoded in base64url. The integer is likely a counter of the number of that type of identifier, that were previously created in the same millisecond.
Example: "ciq:C:F3:3:X0s5eA:Aq:example.com" // Type "C:F3:3" contains a base64url timestamp-id and domain name.
Common Identifier Qualifier Format / Canonical Identifier Qualifier Format (CIQ)
A format for writing self-tagged identifiers, primarily universal identifiers, and Locked Identifiers. It can also be used to specify Single-site User Identifiers, etc. It adds meta-information to identifiers. It requires every conforming identifier to start with a "format-prefix" followed by "type information". The "type information" specifies what "standard" the identifier follows, what payload format the identifier uses, what type of lock the ID uses, and what Identifier Unlock Verification Method RPs should use to verify it.

The format is composed of five sections, separated by colon characters. "ciq:NID:lockType:formatId:payload". The sections are format-prefix, namespace_id, lockType, formatId and payload. (Note that the payload MAY contain additional colon characters.) The namespace_id specifies the standard that the identifier follows. (i.e. the standards organization) Each namespace defines its own types, otherwise known as "rules" and "formats". The lockType specifies the type of lock (and the IUV Method defined by the standard) that the ID follows. The combination of the namespace_id, lockType and formatId specify the "type" of the identifier. The formatId specifies the set of rules that the payload contents should follow. This includes the order and encoding of any items in the payload.

The combination of the namespace_id and lockType specifies what Identifier Unlock Verification Method should be used. (Ex: "C:F1:3") For example, the "C:F1:3" type specifies a Federated UserId type and a particular Federated UV Method to use, and the method specifies the Backer VM to use. The format allows various characteristics of the identifier to be determined. The format allows RPs to determine what Identifier Use Requirements each identifier requires.

When users try to create a login at an RP using their own UserId (or change their UserId), the RP needs to easily determine the type of the UserId, and if it can perform the required operations. (e.g. An RP must not register a Locked Id to any of its users, unless the user can unlock the ID.)

There are three main categories of UserId. "Single-site", "Self-contained", "federated".

In the "C:A:" types, the "C:A:9" type can contain basic character data. ("C:A:9" stands for "basic character string".) This special type makes it easy to convert any existing username into a CIQ identifier. Just prefix the username with the characters "ciq:C:A:9:". This allows a single database, etc. to contain both Single-site UserIds and Locked Ids.

Examples:
  • "ciq:C:A:1:1234567890" // Type "C:A:1" contains a decimal integer.
  • "ciq:C:A:2:M4rj-3q" // Type "C:A:2" contains a base64url encoded integer.
  • "ciq:C:A:3:X0s5eA:Aq" // Type "C:A:3" contains a base64url timestamp-id.
  • "ciq:C:A:9:little_bo_peep12345" // Type "C:A:9" denotes a "basic character string".
  • "ciq:C:B1:1:M8h2Dz0Wyv_lViQ4Nr0TN5BfJ" // Type "C:B1:1" is a base64url encoded JWK public key.
  • "ciq:C:B1:2:K8h3_TfXr6ZtLq7d1m8k" // Type "C:B1:2" is a base64url encoded COSE_Key public key.
  • "ciq:C:B1:3:P83_f82hdgT6B9NqL0Dz" // Type "C:B1:3" is a base64url encoded SHA-256 hash of the user's id.
  • "ciq:C:F1:1:1234567890:ACMA_org" // Type "C:F1:1" contains a decimal integer and a SimpleBackerId.
  • "ciq:C:F1:2:M4rj-3q:ACMA_org" // Type "C:F1:2" contains a base64url encoded integer and a SimpleBackerId.
  • "ciq:C:F1:3:X0s5eA:Aq:ACMA_org" // Type "C:F1:3" contains a base64url timestamp-id and a SimpleBackerId.
  • "ciq:C:F3:1:1234567890:example.com" // Type "C:F3:1" contains a decimal integer and domain name.
  • "ciq:C:F3:2:M4rj-3q:example.com" // Type "C:F3:2" contains a base64url encoded integer and domain name.
  • "ciq:C:F3:3:X0s5eA:Aq:example.com" // Type "C:F3:3" contains a base64url timestamp-id and domain name.
  • "ciq:C:F4:1:234789:example.com" // Type "C:F4:1" uses "ua protocol 2". It is authenticated via a different protocol than "C:F3:1".
  • "ciq:C:email:1:joe@example.com" // Type "C:email". Payload is an email address.
  • "ciq:C:webfinger:1:joe:example.com" // Type "C:webfinger". Payload is a user account and domain name.
  • "ciq:C:IndieAuth:1:example.com/asmith" // Type "C:IndieAuth". Payload is a domain name and page.
  • "ciq:C:A:8:f987b543" // Type "C:A:1" contains a hexadecimal integer.
  • "ciq:C:F1:8:f987b543:ACMA_org" // Type "C:F1:1" contains a hexadecimal integer and a SimpleBackerId.
  • "ciq:C:F3:8:f987b543:example.com" // Type "C:F3:1" contains a hexadecimal integer and domain name.
Identifier Use Requirements
The requirements an RP must meet for it to support the use of a type of identifier. (For example, for an RP to support user login using the specified type of identifier.) There are three main categories. "Single-site", "Self-contained" and "federated". The "Single-site" type requires the RP to store some set of "Credential Verification Rules". (The RP can choose the number of CVR and what types to support.) The "Self-contained" type requires the RP to support the CVR type(s) contained in the identifier. The "federated" type requires the RP to remotely connect to a federated server for user authentication. (i.e. It uses a Backer VM.)

Note: With "Self-contained" and "federated" the RP can always require its own CVRs *in addition to, or instead of* those required by the UserId. When using the CVR belonging to the Locked Id to authenticate a user, these types complicate the "password reset" problem. This is because the RP does not control those CVR, and therefore cannot change them. Also, the RP must guard against unauthorized "registration" of Locked Id IDs.

UserId Registration (A.K.A. User Registration.)
A type of record at an RP that assigns a UserId to a user. The record contains the UserId and some way of verifying the user in the future. (i.e. Some set of Credential Verification Rules.) Creating a UserId registration is the same as User Login creation. (i.e. See createUserLogin.) The UserId in a registration can be a Single-site UserId or a Locked Id. (i.e. It can be created by the RP, or it can be created externally to the RP, and claimed by the user.)

User Login creation may not be the same as "creating an account" at the RP. (Because some RPs may require an additional step to "create an account".) It identifies a user to the RP, and allows the user to "login" to the RP again at a later date, but it may not necessarily create a separate "service account" at the RP. This is because an RP may allow multiple UserIds to share a single "service account". An RP can allow multiple users to access a common account. This is done with each user being assigned a unique UserId. (A UserId may identify a person or a device, etc.) An RP can create its own UserIds (i.e. a Single-site UserId) or allow a user to register a foreign UserId (i.e. a Locked Id). When attempting to register a Locked Id at an RP, the RP must ensure that the user can unlock the ID.

CIQ Type Specifier / User Identifier Type
The type of a CIQ formated UserId is the combination of its namespace_id and lockType values. For example, the type of "ciq:C:A:3:X0s5eA:Aq" is "C:A:3".
Multi-site UserLogin
Another name for a Multi-Site UserId. A single UserLogin used to identify a user at multiple RPs. (i.e. It is a single Locked Id and the associated unlock mechanism, private key, etc.) Any Multi-Site UserId, such as an email address or a "federated UserId" etc., can be used as a Multi-site UserLogin. (As long as it is used at multiple RP.)
Important Note: This specification does NOT implement a Multi-site UserLogin, as that would result in reduced user privacy. If the same User_ID were used at multiple RPs, that would make it easy to track a user at different RPs. RP websites could collude together, or they could sell advertising statistics based on User IDs. RPs or advertising agencies would be able to easily track user activity, or correlate a user's behavior at different RPs, based on the UserId. This specification uses *site-specific* user identifiers (a different UserId at each RP) specifically to make it more difficult to track a user at different RPs.
User Badge (Also known as a FlexBadge or ReflectionBadge.)
A group of related User Logins, organized into a single functional unit. A Badge is a way of organizing User Logins, in order to simplify the Login System for users and hide most of the complexity. A Badge represents an "online identity". A Badge is designed to hold one User Login for each and every RP. A single Badge can be used all over the internet, at each and every RP. A Badge gives the Login System something consistent to display to users across different RP (the Badge name), instead of the, more complicated, User Login information for each and every RP. (i.e. The UserId for the User Login, etc.)
Each Badge can be used all over the internet, at each and every RP. Users typically only have to interact with one or two Badges, instead of the details of hundreds of individual User Logins. A Badge works best when it contains only one User Login for each RP. This makes the login prompt very simple. Badges are only visible to the user. They are never given to any website. User Logins can be moved between Badges. So they can be reorganized later. Badges preserve user privacy and prevent user tracking. See Badge Detail.

The login system internally uses a different User Login (and UserId) for each RP. However, the detailed information is usually unnecessary to users, and should be hidden.

Badge Detail

A Badge is a way of simplifying User Logins for users. It organizes them into groups. A Badge presents a single entity to users, while internally hiding hundreds of UserLogins.

A person typically needs only one or two Badges, no matter how many online accounts they have. A user only needs another Badge if they want more than one account at some websites, and they want to group those additional accounts together, as a separate "online identity".

A Badge is a way to get some of the benefits of using a single User_id everywhere, while not sacrificing user privacy. A Badge is a facade. It is a single interface to a group of UserLogins, using them all together as a single functional unit. A Badge is designed to look like a single "Locked Id" to users. But internally it uses individual UserLogins, so that it can give each RP a different UserId. (So that the same UserId is not used at multiple RP.) This is done to preserve user privacy.

A Badge usually contains only one UserLogin for each website, as that makes things easier. UserLogins can be moved between Badges. So they can be reorganized later.

When logging into a website, the system will find all the User Logins, in all the Badges, for the website that is being logged into. If there is more than one such User Login, then the system may ask the user to choose between them, and will display a list of the User Logins to the user.

Badges make the login process much easier, because the User Login list only needs to display the name of the *Badge* that the User Login is contained in. The individual User Logins usually do not have a name. (i.e. The user can select which *Badge* they want to use. The user does not need to know anything about the User Logins that the Badge contains.)

Badges work better when they contain only one User Login for each website. Because it allows a simpler "existing User Login" list to be displayed during login. If a Badge contains more than one User Login for a website, then that makes the list slightly more complicated, and logging into that website slightly more difficult.

If a Badge contains multiple User Logins for the same website, that will cause nearly "duplicate entries" in the "existing User Login" list. (i.e. Multiple entries in the list will have the same Badge name.) To prevent confusion, each of the "duplicate entries" is assigned an individual name or id number to help tell them apart, and the "duplicate entries" in the list will display the extra name. This adds another thing that users must remember.

User Tracking and Online Privacy

It would be easier for users to use the same Locked Id everywhere online. However, doing that would result in severely reduced user privacy. Because doing that would make it very easy to track user activity at multiple RPs. Currently, RP websites sell advertising by installing third party scripts on their websites, and they sell their user data to marketing companies. If users were represented by the same ID at different websites, then that would make it easy for data to be aggregated together and be used to track user activity between multiple websites.

Websites could collude together to aggregate data and track users. Websites could sell advertising statistics based on User IDs. RPs or advertising agencies would be able to easily track user activity, or correlate a user's behavior at different RPs, based on the UserId.

In order to preserve user privacy, this specification uses *site-specific* user identifiers (a different UserId at each RP) specifically to make it more difficult to track a user at different RPs. (These are likely Single-site UserIds.)

Badge implementation

A Badge is a special kind of group of User Logins. It contains a "Map" or "associative array" that has one "slot" for each RP. Each "slot" contains contains all the information for that RP, including one or more UserLogins.

When logging into a website, the system will find the UserLogin(s) for the website that is being logged into. If there is more than one such UserLogin, then the system may ask the user to choose between them.

A single Badge should not be shared between multiple users. Each user should have their own Badge. (A user may have multiple Badges.) A Badge typically contains a "name", some "master keys" (backup keys for UserLogins) and a map of RP domain names (which contain the UserLogins).

A Badge has a name and an id, and possibly some other information. The Badge ID is used in the browser to identify which Badge is to be used. No Badge information is ever given to any RP. A UserLogin is retrieved from inside the Badge and that is used to create a "proof of identity" that is sent to the RP. A Badge is stored in a Login Manager (or in a User Authenticator or a browser). The Badge id is kept secret from RP websites. If websites were given a "Badge id" as part of an identifier, then it would tell the website that the user has multiple accounts at the website, and which Badge the user selected to login with.

If users need multiple Badges, then each Badge will likely be assigned a user role. (One for each of: Work, Personal, Family, etc.)

Badges greatly simplify using UserLogins for users. They reduce the login options that are displayed. Badges, and UserLogins hide allow the system to hide all individual UserIds, and instead only display the Badge ID to the user. (This allows the actual UserId values to never be seen by the user.) This greatly simplifies things for users. For example, when logging into an RP, the system does NOT have to display to the user a list of UserIds registered for the RP. This would likely have to display to the user a list of long, 65 character alpha-numeric strings with little significance. Instead of this confusing mess, the system only displays the Login Badges that contain a UserId registered for the RP. As a second example, regardless of what RP the user wants to log into, the same set of Badges can be displayed to users. (If a Badge contains a UserLogin for the current RP, then the Badge is displayed as a login option. Otherwise the Badge is displayed as a "create account" option.) The user selects which Badge to login with, and the system automatically uses the contained UserId for the current RP. (This allows the actual UserId values to never be seen by the user.)

Badges work better with only one UserLogin per slot. Slots with multiple items increase the complexity when using a Badge. For this reason, it is recommended that, most of the time, users should only store one UserLogin per RP domain name. This maximizes the benefits of Badge. However, the Badge are capable of holding multiple UserLogins per RP. This allow users to store two or more UserLogins for certain RPs that merit the additional complexity.

Login Manager
A piece of software that stores user authentication data (A.K.A. User Logins), necessary to login to RPs. It stores UserIds, passwords, public and private keys and any other secrets needed to login to RPs. (i.e. It stores "credential sources".) It is a more advanced version of a "password manager", because it stores more than passwords. (It can also be called a "credential manager", etc.) It allows the User Login data to be viewed and/or edited, etc. A Login Manager can easily also work as a User Authenticator. To do so, it must be able to generate a "proof of identity" and must support the connection protocols required by a Login Manager, so that a browser can connect to it. (i.e. NFC, Bluetooth, WiFi, USB, or as a Web Service.) A Login Manager can be located on a physical device such as a "Security Key", on the internet as a Web Service, or on the user's local machine, or mobile phone etc. Typically, all "credential sources" should be stored in a Login Manager, as it is more secure. And Login Managers are usually either portable or usable remotely. See LoginManager API.
User Authenticator
A software or computing device designed to generate proof of a user's identity. It must support connection protocols so that it can be connected to via a browser. (i.e. NFC, Bluetooth, WiFi, USB, or as a Web Service.) It works by receiving a request from a browser, for an RP, and returns a "proof of identity" for use at the RP. Generating a cryptographic "proof" allows it to keep any credential sources (such as private keys) secret. A User Authenticator may also work as a Login Manager, if it provides sufficient UserLogin and LoginItem editing capabilities. When looking at the LoginManager API, there are 3 required Authenticator functions. findUserLogins, createUserLogin, buildProofForRp. (They usually accept the "rpClientData" argument.) See User Authenticator Detail.
User Authentication Device
A physical computing device that stores or generates user identity credentials. It is a type of User Authenticator. It may connect to a computer though a physical connection, or wireless communication protocol. Some examples are a USB key, or a chip on a keyring using Bluetooth, etc. A mobile phone may be used as an authentication device. i.e. as a digital key to unlock features in a different device, such as a computer, TV set, etc.
User Credential
Data given to an RP to provide proof that a user is who he claims to be. (Generically, a credential is data one entity presents to another in order to authenticate the former to the latter [RFC4949].) In this specification, a credential is single-use. This is to ensure that a credential cannot be copied and used by others. During a login, a credential is created from a Credential Source and some random value provided by the login verifier (usually the RP). During the next login, a different credential will be generated. Each credential must be validated, and must meet the requirements of a Credential Verification Rule, usually stored by the RP. An RP may require multiple credentials for user authentication.

In this specification, the CLS Request sent to the RP can contain multiple credentials. (i.e. credential proofs.) Therefore, each credential must have an id to identify what Credential Verification Rule it is for. Some examples of a credential are a "username and password hash", a "digital signature" (i.e. the signature of a private key ), or a federated credential.

Single-use credentials are common in most computer systems that use public key signatures. These credentials are designed to be proof that the user has access to the specific "credential source" used in the Credential Verification Rule. These types of credentials can also be called a "credential assertion".
Federated Credential
A credential that uses an "identity provider". See Federated UserId.
Authentication Assertion
Another name for a CLS Request that uses the cls.opId.login reqOp. (Copied from serviceOp.)
Credential Source
The secret data that is used to create a User Credential. It is commonly a password or private key, etc. Typically, a credential is created from a "credential source" in response to a challenge from an RP. A credential is time-stamped and is single-use. In contrast, a credential source can be used multiple times. A UserLogin can contain multiple credential sources. A Credential Source is created from cls.opId.createUserLogin and setActiveCredentials.
Credential ID
A string of characters that uniquely identifies a Credential Source that belongs to a UserLogin. Example: "cd2". A credential id is also used to identify the Credential Verification Rule that matches the Credential Source, and every User Credential that is created from the Credential Source. (For example, Credentials are contained inside an Authentication Assertion, and sent from the browser to the RP.) A Credential Id is typically permanent, and never reused, even if the Credential Source is "deleted". (Because a Credential Id is stored by the RP, to identify a Credential Verification Rule. i.e. a public key, etc.) A Login Item exists in a Login Manager or User Authenticator. A Login Item is uniquely identified by a LoginItem Permanent ID, "lipId". The combination of a lipId and a credential id is also guaranteed unique within a Login Manager.

The Credential ID (possibly with some additions) is used several times in the CLS Request to identify the Credential Verification Rule for a particular User account. In the "cvid" property of the CVR registration section. In the "cpid" property of the "credentialProofList" section. In the "kid" value of the signature header.

Credential Verification Rule (CVR)
Data or algorithm used to determine if a credential is valid or not. It is a test, or a required condition, to determine if the credential was created from the appropriate Credential Source. (Note that in this specification, a credential is single-use. It is created from a Credential Source, which is kept secret. It is usually some type of digital signature.) There must be an associated CVR for each and every Credential Source. For example, a CVR may be, or contain any number of, a public key, a password, a certificate, an algorithm, a database record, an API call to another website, etc. In order to be useful, CVR values must be known. They can be public, or they can be stored by a verification entity (such as an RP).
CVR values are used during "User Authentication". A CVR value is usually a part of the User Authentication Credentials stored by the RP. (Or it can be public, etc.) A CVR is usually the opposite of a "credential". A CVR is a required condition, while a "credential" is proof of a condition. (However, in the case of a "password", both could be the same value.) See User Authentication Process.
During a login attempt, an RP typically requires that a "proof of identity" must satisfy some subset of the CVR values in order to be valid.
"Leaky" Credential Verification Rule
A Credential Verification Rule that reveals credential source secrets. (i.e. A CVR that can be used to determine the secret "credential source" that it verifies.) In contrast, a "no-leak" CVR can only be used to verify a "proof", and cannot be used to determine the "credential source". A leaky CVR means there is a problem with the one-way function used to create the "proof" from the "credential source".

A regular "password" is an example of a CVR that "leaks". In order to use a "password", an RP must know the secret "credential source" (i.e. the password itself is the source). A public-key is an example of a "no-leak" CVR. In this case, the RP only knows the "public key", which is NOT the "secret". The "secret" is a private key.

Multi-Site UserId Credential Verification Rule
The Credential Verification Rules that are "tied to" a Multi-Site UserId. (i.e. A type of Locked Id.) They are applicable to all RPs. They must be available to and usable by all RPs.
For Example, with a Federated UserId, they are commonly published in a "UserId Certificate" document, that is signed by the "Backer". They can also be published at the "Backer" domain name, or the UserId certificate containing them can be delivered to the RP by the user during the authentication process. The Self-contained type contains the CVR itself. (i.e. in the payload.)
All compliant RPs must verify all "Multi-Site UserId CVR" before using them. Before allowing a user to use a UserId to "sign-up" or "register" himself. When a user tries to sign-up, or "register" using a Locked Id, all compliant RPs MUST require that the user unlock the ID. i.e. Provide valid proof of user-verification of the UserId. The RP must (1) recognize that the UserId is "a Multi-Site UserId", (2) obtain the "Multi-Site UserId CVR" for the UserId, and (3) validate that the proof the user submitted satisfies the Credential Verification method.
Credential Verification Method
A process by which a credential can be proven to be valid or not. Each credential must have an associated method by which its validity can be verified. Usually, credentials of the same "type" share the same verification method (e.g. public-key, password, federated), and each credential only has a small Credential Verification Rule to test the results of the method against. However, in advanced cases, an RP may allow a credential to define its own Credential Verification Method.
User Authentication Credentials
The collection of all data or algorithms stored by an RP to potentially authenticate a user. It includes all "User Credentials" (i.e. Credential Verification Rules), as well as all backup keys, stored by the RP for a UserId. (See serviceOp "cls/setActiveCredentials".)
CAPIS HTML Element
One of the HTML elements introduced in this specification. (i.e. CAPIS Link, CAPIS Anchor and CAPIS Form.) They are used to embed RP Configuration Options and RP Service Triggers in HTML. User authentication is one such service. See CAPIS HTML Element detail. The elements are CAPIS Link, CAPIS Anchor and CAPIS Form. They each have two special HTML attributes. The attribute "capis-config" stores RP Configuration Options), and the attribute rel="capis-base" (or handling=capis-trigger for forms) defines the element's role, and gives it a special behavior.
Example: <a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login" '>Login</a>
CAPIS Link HTML Element
A Link HTML Element with the special attribute rel="capis-base" (and required capis-config attribute). It is one of the CAPIS HTML Elements. The capis-config attribute contains the Client Configuration Options. These are RP Configuration Options that apply to the entire HTML page document. See CAPIS Link Detail.
CAPIS Anchor HTML Element
An Anchor HTML Element with the special attribute rel="capis-trigger". It is one of the CAPIS HTML Elements. If the browser understands this specification, then it does not behave like a normal HTML anchor. When clicked, it will perform the CapisControl.activateTrigger, and then perform the serviceOp property. It will not load the URL contained in the "href" attribute. It uses the "href" attribute exclusively as a "fallback" URL. (Only older browsers, that do not understand the rel="capis-trigger" attribute, will use the href value.)
CAPIS Form HTML Element
A Form HTML Element with the special attribute handling="capis-trigger". It is one of the CAPIS HTML Elements.
CAPIS specification
This specification. See CAPIS. It includes the CAPIS HTML Elements.
RP Service
A service offered by the RP. The service requirements are specified in a RP Service Descriptor. An RP typically publishes a list of the services it offers in the RP Config Document, or in the Client Configuration Options in an HTML page. The document contains a list of RP Service Descriptors, describing the service's abilities, requirements and Service Endpoints. "User Authentication" is one type of service that can be offered. See Capis Login. The service receives an RP service request (such as a CLS Request)
RP Service Operation
An operation offered by an RP Service. An RP Service can provide any number of operations. Example: See CLS Operation List.
RP Service Descriptor
A JSON object containing the capabilities and requirements of an "RP Service". An RP publishes descriptions of what RP Services it provides in an "RP Config Document" or serviceList.serviceItem. Browsers use the descriptors to understand what types of services the RP provides/supports. A descriptor contains: (1) The id of the service. (2) The protocol. (3) The endpoint URI. (i.e. What URI the browser should use to send an HTTP POST containing service request information.) (4) The other features that the service supports. See the CLS Service Descriptor Detail. (The CAPIS RP Service Descriptors may use JSON Web Service Descriptor Format. JWSD)
RP Service Trigger
An element in a computer program, used to invoke an RP service. It is commonly an HTML element, such as an anchor, button or form, but it can also be a menu item or other UI element in the browser chrome. For example, a regular HTML form that asks for a username and password (i.e. a "login form") is commonly used as a trigger. Submitting the form sends data to the RP, and receives a reponse. (In other words, it invokes the "Service" at the RP.)
CAPIS defines a few new CAPIS HTML Elements for use as triggers. These are the CAPIS Anchor and CAPIS Form. The "CAPIS Service Triggers" differ from regular HTML elements (anchors, buttons and forms) in that: (1) They are MARKED as an "RP service trigger". (2) They contain Trigger Configuration Options. (These must include the serviceOp property. And that contains the "protocol" ID of the service.) (3) They request a Service Response, not HTML. The response is processed by the CAPIS Service Invocation Flow. Also see CLS Response. Triggers also work without javascript.
Example: <a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>
Login Trigger
An element in a computer program that will activate the User Login process. (i.e. The User Authentication process.) A Login Trigger sends data to the RP and awaits a response. (i.e. It is a type of RP Service Trigger.) It is typically a User Interface element. Common examples are HTML elements, such as an HTML anchor, button or form. But it can also be a menu item or other UI element in the browser chrome. (i.e. It does not have to be a user prompt.) Traditionally, a "login form" is used as the trigger. Submitting the form sends data to the RP. In other words, it invokes the "Login Service" at the RP.
login form (Traditional)
A regular HTML form requesting the username and password in order to login the user. The submission of this form is commonly used as a Login Trigger.
RP Service Request
A communication from the browser, or other agent, to an RP Service Endpoint, asking the RP to perform an RP service. For an example implementation, see CLS Request.
RP Service Response
A return communication from the RP, to the requestor. In response to an RP Service Request. For an example implementation, see CLS Response.
RP Service Endpoint
A URI (at the RP) that has an RP Service listening to it. It listens for an "RP Service Request" and will perform the requested operation. (e.g. A CLS Request may ask the RP to perform a user login. "cls/login" See endpoints.) A Service Endpoint is specified in a RP Service Descriptor (of a RP Config Document). Endpoints typically receive HTTPS POST requests and return an HTTPS response. The response is typically a JSON document, containing either return values (such as a success code) or describing an error. For example, see CLS Response Detail.
RP Config Document
A JSON document published by an RP that describes the RP and its public services using Capis format. The document includes a list of RP Service Descriptors, these identify the public RP Services the RP offers. A descriptor specifies the abilities and requirements of an RP Service. The list can include login services. See RP Config Document Detail. (The CAPIS Document contains the "RP id", etc.)
JSON style property list
A set of name-value pairs written in the format of JSON object properties. The format is standard JSON, except that it allows property names and string values to be either enclosed in single quotes or double quotes. The ability to use single-quotes was added for convenience, because HTML attribute values can be double quoted, and that interferes with standard JSON quoting. The entire set of properties will be extracted into a single JSON object.
Example: <a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>
RP Configuration Options
Any of the name-value pairs created by the RP and given to the browser in order to configure the browser's interactions with the RP. The options are usually embedded within HTML markup as a set of JSON-style properties in the "capis-config" attribute of one of the CAPIS HTML Elements. The options give the browser data or instructions about RP services without using javascript. This makes creating CAPIS enabled HTML easier, and CAPIS will work without requiring the browser to enable javascript for the RP. The options currently come in two types, Client Configuration Options and Trigger Configuration Options. See RP Configuration Options detail.
Example: <a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>
CapisAPI.callOptions
The "callOptions" argument supplied to the CapisControl.invokeServiceAction function. This argument customizes what RP service request is created. It is a JSON object. It is commonly created from the Trigger Configuration Options, of the RP Service Trigger HTML element that was activated. (e.g. A CAPIS Anchor.) Note that an RP Service Trigger HTML element does not need to be activated. The API can be called directly, and the "callOptions" can be specified by the caller.
CapisAPI.serviceOp
A supplied argument when making an RP service request. The argument to the CapisControl.invokeServiceAction function. The value is commonly copied from the serviceOp property of the Trigger Configuration Options, from the HTML element that was clicked.
CLS Request
A communication from the browser to the RP service endpoint, asking the RP to perform a user authentication service, such as "login". It is a type of RP service request. It consists of a single JSON object. It contains a requested user authentication reqOp and a "proof of identity", along with any other necessary data. See CLS Request Detail.
CLS Response
A communication from the RP to the browser, in response to a CLS Request. It consists of a single JSON object. See CLS Response Detail.
Login Status
The status of the User Authentication at an RP. This is the result of the CapisLogin.getLoginStatus API call. There are 4 types. "logged_in", "logged_out", "pending_login", "pending_logout".
Proof of Identity
A set of data that proves a user is who he claims to be. It includes a "claimed" UserId, the challenge from the RP, and a set of User Credentials for that UserId. (Credentials such as cryptographic signatures or passwords.) It proves that the user knows the secrets for the claimed UserId. (i.e. the private key, password, etc.) This specification uses a UserId Assertion and a UserId certificate as the component parts of the "proof-of-identity". The JSON Web Signature is the UserId Assertion. It is sent from a browser to an RP in an "CLS Request".
More details.
A "proof of identity" contains a UserId, an array of "credentials", a creation date, an expiration date, and the "audience" that it is intended for. (Note that all of the "credentials" included in a "proof of identity" must be for the same UserId.) The ability to contain multiple credentials, each of a different type, allows a single "proof-of-identity" to be used for Multiple Credential Authentication and multi-factor authentication. An RP stores some set of Credential Verification Rules for each UserId. The RP can decide which rules it requires, under which circumstances. A "proof-of-identity" contains a set of credentials. Each of the credentials must specify the "id" of which rule it is for. In order to login, the "proof of identity" must have a credential for each of the required rules. (Usually, the RP requires all the rules to be proven, so the proof should have one credential for each of the rules.)
CAPIS Trigger Behavior
The new behavior defined for CAPIS HTML Elements. (The Link, Anchor and Form.) It performs CapisControl.invokeServiceAction on the "serviceOp" and other Trigger Configuration Options, defined in the "capis-config" HTML attribute. (For example, in a CAPIS Anchor HTML element.) If the browser understands this specification, then a CAPIS Anchor (i.e. An HTML element marked with the rel="capis-trigger" attribute) will perform the CapisControl.activateTrigger, and then perform the CAPIS serviceOp. It will not load the URL contained in the "href" attribute. The serviceOp has a defined format, however, there are no defined values in CAPIS. (Note that Capis Login has defined several opId values.)
User authentication process (Generic)
The process by which a user's identity is verified. For Example: The RP web page contains a Login Trigger, which the user activates. (Clicks the anchor, or fills out the form and submits it.) The CAPIS User Authentication Process is one such process.
CAPIS User authentication process
The process by which a user's identity is verified using CAPIS. Uses the RP Service Invocation Process. The RP issues a challenge in the Client Configuration Option, somehow the browser is triggered to start the login (by user click, etc.), the browser creates a user prompt, the user selects a UserLogin to use, the browser creates a CLS Request (which includes a claimed identity and some sort of "proof") and sends the request to the RP. Then the RP performs the User Identity Verification process on the submitted request and issues a CLS Response. See RP Service Invocation Process.
RP Service Invocation Process
The special CAPIS Service Invocation Process defined in this specification. It details the steps CAPIS-compliant browsers should implement. A detailed overview of the process is provided in the CAPIS Service Invocation Flow.
User Identity Verification
The process by which a user's identity is verified. The process by which a "proof of identity" is verified. The user claims a UserId and provides a "proof of identity". The RP then verifies the user's claims are valid. If the proof is valid, then it proves that the user is who they claim to be. Verification ensures the proof is valid, was not faked or tampered with, and meets all the requirements of the RP. In particular, an RP can require multiple factors of authentication. See User Authentication Detail.
Multi-User Account Access, (A.K.A. "Account Sharing" and "Account User Access Control")
The ability for multiple UserIds to access the same account at an RP. The ability for an account to grant access to multiple authorized users. This feature allows an account owner to "share" their account with other users, without giving the others the owner's login details. (i.e. the owner's username and password, etc.) The other users are assigned an account_permission_role. The other UserIds can be people, or can be authorized devices or services. This ability is usually implemented by an account maintaining a list of approved UserId, and each UserId is assigned its own account_permission_role. This ability usually requires the RP to use a "one-to-many" UserId to account_id mapping. See RP Requirements.

This ability also provides an easy way for an RP to support Multiple-account Access. Since a single UserId can be listed as an authorized user on multiple accounts at the RP. (For example, a user can have their own account at the RP, and can also be listed as an authorized user on other accounts.) If a single UserId can access multiple accounts, then the RP may allow the user, after logging in, to decide which account he wants to access.

More

Because each user has their own UserId, it allows the RP to manage and track how much each user uses the account.

RPs MAY allow accounts to impose additional credential requirements on its authorized users. But this is uncommon. Typically, the UserId does not need any additional User Credentials to access the different accounts at the RP. (i.e. One set of credentials to login to the RP, other passwords or public keys for different accounts, etc.)

This ability also allows the same user to register at the RP with multiple UserId. The user can access their account with any UserId that is authorized. (i.e. This allows a user to change his UserId or to maintain multiple UserId.)

Multiple-Account Access
The ability for a single UserId to access multiple accounts at an RP. After a user logs into the RP, they can somehow select which account to access. This ability does not necessarily require the RP to use a one-to-many UserId to account_id mapping. (But it is an easy way to implement it.) See RP Requirements.

An easy way to implement this feature is to first support Account User Access Control. (i.e. Account Sharing.) Then, have each of the accessible accounts include the specified UserId as an authorized user. (And give the UserId an account_permission_role.) See grant access.

The RP must provide some way to allow users to select which account they want to use. Typically, this is done in one of the following ways. (1) During login. The user can include an account_id in the login request. (2) Immediately after login. The RP displays a list of what accounts the user has access to, and the user must pick one. (3) Allow switching at any time. The RP adds a link (or similar) to the HTML page, providing a way for the user to view the list of accessible accounts and select the one they want to access. (4) Multiple accounts at the same time. The RP provides an interface that allows a user to view or make changes to multiple accounts at the same time.

Authorized User
A UserId that is allowed to access an account at an RP. Typically, each account either has a single authorized user (i.e. the "owner" of the account), or has a list of authorized users. Each of the authorized users is also assigned an account_permission_role, which defines what features of the account the user can access. See Account User Access Control. Each authorized user is a UserId, and has its own Credential Verification Rules that it uses to log into the RP. (i.e. Some set of passwords or public keys, etc.) Once a UserId has logged into the RP, the RP can then allow it access to the accounts that it is authorized to access.
Attestation
A statement that a party has confirmed or authenticated that a process or output works correctly and meets the necessary requirements. When describing credentials, an attestation is a signed statement, backed by the device manufacturer, etc. stating that the User Authenticator and its process has been certified. That the authenticator has created the item (the credential) in the appropriate manner. (According to the standard.) Attestation is a promise (a guarantee) that the Authenticator, and the data that it emits, follows a standard. Attestation is also a way of identifying the creator of an Authenticator, and specifying the Authenticator's capabilities. (An RP may use the attestation data to restrict what Authenticators it will accept.)
Typically, a Login Manager is created in such a manner that it can only create credentials (key pairs, etc.) in a certain manner. The authenticator contains two special attestation items, put in the software or on the device during manufacture, by the creator (the device manufacturer, etc.). The two special items are, an attestation key pair, and an Attestation Certificate. The certificate contains the attestation public key, and is signed by the device manufacturer. Both of these attestation items are typically NOT unique. The same items are inside a large number of other authenticators of the same class. (Typically tens of thousands.) At registration time, a Login Manager is instructed to create a new key pair (for an RP website). The authenticator creates the new key pair, then it takes the newly generated public key and "signs" it with the special attestation private key. The Authenticator creates a result object (it may be a JSON object), puts in it the new public key, the signature, and the Attestation Certificate, then sends it back to the caller. The two attestation items provide proof that the newly generated public key was created in a certified manner. That it follows a certain standard.
JSON Web Signature
A JSON object that contains a "payload" string and a "signatures" array. (i.e. The array must contain one or more public key signatures.) This specification uses the "standard JWS format" and does not use the "compact format". The payload is the base64url encoded version of some original data. (Typically another JSON object.) Each "signature" can use a different signature algorithm and key. A "signature object" has three properties, a "header" JSON object, a "protected" header string, and a "signature" base64url encoded byte string. The "protected" header specifies the cryptographic algorithm. The "header" specifies the key id. (See the JSON Web Signature RFC.)
Example: JWS = {"payload":"mJh48Q...", "signatures": [{"protected":"eyJhb...", "header": {}, "signature":"cC4h..."}, {}] };
Capis Login
A way of performing User Authentication, using CAPIS. It is a User Authentication service, provided by an RP. References to it must be included in the RP's HTML web pages. This is done using CAPIS. Capis Login defines the Capis Login Flow, CapisLogin API and LoginManager API. Capis Login defines the format for the CLS Request. Capis Login is a User Authentication CAPIS service. It is also the primary example of an RP service.
CAPIS (A Way to Define Website Services)
Abbreviation for "Common Architecture for Publishing Internet Services". It is a way for websites to publish what services they offer, and how to connect to the services, inside of HTML markup. It is HTML attributes that contain JSON. The JSON includes a list of "RP Service Descriptors". CAPIS is a way to specify website services and protocol data in HTML files, without using javascript. (It's JSON.) Capis Login is a way to use CAPIS to perform user authentication. (i.e. user login.) CAPIS defines the RP Service Invocation Process, CAPIS Service Invocation Flow, CAPIS HTML Elements and CapisControl API. The primary example of an RP service is for "User Authentication". It is called Capis Login.
CAPIS Login (Alternate)
The Common Authentication Protocol (and) Identity System. May change to something else. CAPDA. Common Authentication Protocol and Data Format. This is the name of the standard defining one type of authentication communication between the browser and the RP. The names and behavior of the configuration options, request options, the definition of the "support document" and having the "authentication request" deliver a single JSON item, these are all a part of CAPIS.
Note that the changes to HTML are NOT a part of CAPIS. They are covered by a separate specification and can be used with an alternative to CAPIS to communicate between the browser and the RP. (This includes the HTML ideas of: CAPIS Link rel="capis-base", "capis-config", that the contents of "capis-config" is a JSON string, the use of the HTML Link Element to contain Client Configuration Option, and that the web browser can automatically get a separate document from the RP describing how it does authentication. These ideas are defined by the "Web browser and HTML extensions to support the passing of authentication data between the browser and the RP". This is "WESPAD".
CAMIS
Abbreviation for "Common Architecture for Managing Integrated Services". Or for "Camix Services Architecture". Pronounced "kam-suh". (Alternate name is "CAMUA", "Common Architecture for User Authentication"). Pronounced "kam-ew-a". Includes the format for the CLS Request.
CARD
Abbreviation for "CAPIS Architecture Resource Descriptor". These are services available at the website. Each descriptor contains some information for invoking the service, such as the service requirements and the endpoint. Or the descriptor can point to another document that has more extensive service definition. (Such as WSDL.) Used in the "serviceSpec".
Identity Provider
A service that provides a "user identity". That is, a UserId Certificate. The certificate is used with a Locked Id. Usually a person "signs into" the identity provider in order to receive a "UserId certificate". The user can then present the certificate to any RP as part of the User Authentication process. (The user must also present the appropriate credential(s) showing they have possession of the private keys that correspond to the public keys contained in the certificate.)
User Identifier Certificate
A digitally signed statement that contains a "Federated UserId" and a set of public keys, and binds them together. (i.e. It is a UserId binding document".) It is a signed claim from the certificate Issuer, stating that the UserId proved "ownership" of the public keys. (i.e. That the UserId knows the set of private keys that correspond to the public keys.) Therefore, an entity that claims the UserId must be able to use the private keys. A UserId Certificate is different from a regular "Public Key Certificate" in that it uses a UserId as the "owner", instead of an organization, domain name, email address, etc. A UserId Certificate should be issued by the Backer of the UserId, or by an "identity provider" that is delegated by the Backer. (Note: if possible, a UserId Certificate may also contain other types of "Credential Verification Rules" beyond public keys.) See UserId Certificate Detail.
Certificate Issuer
The entity that signed a certificate. (It can be a Public Key certificate or a UserId certificate, etc.) The issuer is supposed to verify the contents of the certificate before signing it. Users of the certificate must be able to get a sig verification keys for each signature in the certificate (if there is more than one), in order to verify the certificate. These are the public keys that were used to sign the certificate. Therefore, the public keys that were used by the issuer to sign the certificate are usually either published publicly or available from the issuer upon request. I.e. From a Backer VM.
User Identifier Assertion
A digitally signed statement that claims that the issuer of the assertion (i.e. the user or browser) is authorized to use a UserId. It provides proof that the issuer has possession of, or access to, the set of secrets (i.e. private keys) that are used in the UserId. A UserId Assertion contains the UserId, a nonce value, the date, etc. and a set of signatures of the private keys. The private keys used to sign the assertion must match the public keys that are associated with the UserId. These public keys may be stored locally by the RP (i.e. as Credential Verification Rules), or they may be bound to the UserId in a UserId certificate or other secondary document. The CLS Request IS a User_id Assertion. (i.e. It contains one in the "JWS" property.) See UserId Assertion Detail.
Signature Verification Key
A public key that can be used to verify a cryptographic signature. In this specification, this is primarily used to verify two types of signatures. (1) A signature in a UserId Assertion, and (2) A signature in a UserId certificate. (The public key for the certificate was created by the Issuer of the certificate.) A signature verification key is similar to a Credential Verification Rule, except that a CVR does not have to be a public key. (It can be a password, algorithm, etc.)
Service Protocol Id
A text string that identifies the protocol to be used. (By CAPIS and by an RP Service.) The Service Protocol Id is used inside the CLS TriggerConfig "serviceOp" value and the RP Service Descriptor "protocol" value. The "serviceOp" property contains the "Service Protocol Id" before the slash, and the opId after the slash.
For example, if the serviceOp is "cls/login", then the service protocol is "cls", and the opId is "login".
WebAuthn
A specification that automates users logging into websites. It differs from this one in that it requires Javascript and forms, custom coding, and that users carry around a separate physical User Authentication Device with them. See Differences From WebAuthn and RP requirements.

HTML Examples:

See the "RP Config Document Detail" for an example of the RP Config Document. It may declare support for additional verification types. (supported.credentialReg.ruleTypes)

The CAPIS Link uses the attributes rel="capis-base" and capis-config. A Capis Link MUST contain a "nonceIssueTime" and "challenge" property.

Examples of CAPIS Link HTML Element:
<head> <link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required"}] '/> </head>
Examples of CAPIS Anchor HTML Element:
<a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login" '>Login</a> ... <a href="/_capis/fallback/logout.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/logout" '>Log OUT</a> ... <a href="/_capis/fallback/proveUserPresence.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/proveUserPresence" '>Confirm your presence</a>
Examples of CAPIS Form HTML Element:

Example 1: Sign a form. This form collects user info before asking the browser to sign the form.
<link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required"}] '/> ... <form action="/_capis/fallback/signForm.html" handling="capis-trigger" capis-config=' "serviceOp":"cls/signData" ' onsubmit="return validateForm(event)"> // User supplied data. <input type="text" name="first_name" placeholder="Enter your first name" /> <input type="text" name="user_email" placeholder="Enter your email address" /> <input type="submit" value="Sign and Submit the Form" /> </form>

Use of a CAPIS Form is only necessary for certain unusual tasks. Mainly this is limited to signData. Usually, forms are NOT needed for User Login creation, as the user DOES NOT need to provide a new "username" to use with the account.

Forms can also be used to do authentication (login, password changes, etc.). This may be useful for some situations. The RP may want to do things with the UserId before the "authentication request" is sent to the RP. Perhaps the RP wants to help the user pick out which UserId to login with, validate the UserId format, etc. Maybe the RP wants to force the user to select from a list of only certain supported UserIds. When doing any of these things, custom javascript on the RP web page may be required.

CAPIS Specification Summary

  1. An RP can publish an "RP Config Document". This describes what types of authentication the RP supports, and the URI and abilities of the RP Services. It also explicitly declares that the RP supports the protocol.
  2. Defines a few new CAPIS HTML Elements. (HTML anchors, links, forms and anchors can be augmented with some new HTML attributes. rel="capis-base", handling="capis-trigger", capis-config="")
  3. One of the new HTML attributes is the CAPIS Link "capis-config" attribute. It contains RP Configuration Options. In particular, the "serviceOp" property specifies the serviceOp to be performed by the RP.
  4. The "redirectUri" configuration property will redirect the browser after authentication is performed.
  5. The anchor and form "CAPIS HTML Elements" do not use their "href" and "action" attributes, respectively. Instead, they will perform the "CAPIS Service Invocation Flow". They will fetch the "RP Config Document", create a "service request" (that includes a "proof of identity"), and send it to the "RP service endpoint". They do not send it to the URI in the "href" or "action" attribute.
  6. Because the "href" attributes of "CAPIS Anchors" (and the "action" attributes of CAPIS Forms) are not used, they can be set to a special "fallback" URI. If a browser follows the URI, it means the browser does not support the CAPIS specification.
  7. The CAPIS HTML Elements have a special activateTrigger behavior.
  8. The CLS Request is a JSON object. It can contain multiple request properties. It also contains the "user_identity" ("request_object.crProofSection"), that contain the various "credentialProofItem.value".
  9. The browser sends the service request to the "RP service endpoint" in whatever manner the RP designated in the RP Service Descriptor. (i.e. In the RP Config Document.) Usually the method is an HTTP POST. In the case where the CAPIS HTML Element that activated CAPIS is a form, and CAPIS is configured to send an HTTP POST, then the browser sends the service request as a special HTTP parameter *in addition to* any regular form data. The default name of the HTTP parameter is capis_request. See endpoint.parameterList.
  10. The defaultValues.capisDocUri of the RP Config Document is a "well-known" URI. (Example: "https://RP_example.com:port/.well-known/capis_config.json".)
  11. An HTML page MUST contain a special "CAPIS Link HTML Element", which defines the Client Configuration Options. These apply to the entire HTML document. The options can include the "protocolHandlerList" and "capisDocUri" properties and the "href" attribute. These determine which "RP Service" is used.
  12. RP Service Triggers (i.e. CAPIS HTML Elements that are not a CAPIS Link) can specify their own Trigger Configuration Options. These options are used as the CapisAPI.callOptions argument.
  13. Browsers can have special behavior for "Anchor CAPIS HTML Elements". The browser can display them in a special color. When a user hovers the mouse over an anchor, the browser can display the available RP options. Using a right-click (or shift-click) can display a dialog asking the user which identity to log in as. A left-click would log in using the "default" identity.
A CAPIS Relying Party must implement the following:
  1. Publish a RP Config Document.
    An RP must explicitly declare, in the form of a document hosted on their domain, that they support CAPIS. This document must contain a list of RP Service Descriptors. The services should define the various user identifier types and Credential Verification Rule etc. that the RP supports.
  2. Create an Endpoint.
    An RP must have a working endpoint, declared in the RP Config Document. A user's browser must be able to interact with the RP's endpoint at the time that the user is signing into a website to prove their identity to the RP and establish a session. (The path to the endpoint is given in the "endpoint.sUri" property of the authentication service descriptor.)
  3. Include CAPIS HTML Elements in the HTML page.
    The RP must notify the browser, by including some changes in the HTML page. These changes can be the inclusion of the new HTML attributes, or the use of the Javascript API.
A CAPIS primary identity authority (IDP) must implement the following:
  1. A declaration of support: An IdP must explicitly declare that they support the CAPIS spec, by publishing a document hosted on their domain. The contents of this document may include paths to supporting resources, as well as a path to public keys which allows for the verification of assertions generated using certificates that the primary has issued.
  2. Authentication page: A user must be able to interact with their IdP at the time that they are signing into a website to prove their identity to the IdP and establish a session.
  3. Provisioning page: A web page must be provided which is capable of provisioning a user that is authenticated to the IdP with a certificate.

RP Requirements Detail

This specification requires that all compliant RP websites use "account ids" that are distinct from user identifiers. In other words, an RP website must not use a UserId as an account_id. For example, it must not use a "username" as an account id, it must not use a CAPIS UserId as an account_id, etc. This enables a UserId to change, without changing the account_id, and (with an additional requirement) it enables a single UserId to access multiple accounts at the RP.

The term "UserId" refers to a string of characters that uniquely identifies a user to an RP website.

This specification requires that all RP websites have a mapping from a UserId to an account_id. (i.e. A database table, or similar, that maps from one to the other.) This is a basic requirement whenever an RP website uses UserIds and account_ids that are different from each other. When a user logs in, the user provides their UserId, then the system uses the UserId to look up the account_id. RP websites could use a simple "one-to-one" mapping or a more complicated "one-to-many" mapping between UserIds and account_ids. A "one-to-one" mapping can only hold one account for a single UserId. A "one-to-many" mapping can hold multiple accounts for a single UserId. The "one-to-many mapping can be used to allow a single user to access multiple accounts. It is common for a mapping from UserId to account_id to also contain other user information. If it does, then it can be called a "User Table". (A "User Table" is a database table that stores user information. It keeps user information separate from account information.)

All RP websites must have a mapping from UserId to account_id. A mapping is necessary because, at the very least, a user's UserId can change. (A UserId can become invalidated, compromised, retired, etc.) The one-to-many mapping is strongly encouraged. The "one-to-many" mapping is necessary for the RP to implement the "Account Sharing" feature. (i.e. the grantAccess serviceOp and the "grant_user_access" request option.) The simpler "one-to-one" mapping, cannot support the "Account Sharing" feature.

  • It can not support "grant_user_access". The website will have no way for account owners to add additional "authorized users" to the account. So a user cannot have the system create an invitation for someone else to join the account. This may be acceptable for certain RP websites. For example, small blog websites. These websites have no reason for them to allow multiple users to use a single account.
  • A single UserId cannot access multiple accounts. (Because the system is not capable of storing multiple account_ids for a single UserId.)
  • Multiple users can still access a single account. However, it is NOT possible for any of these UserIds to access any account OTHER than the single account. (Because the system is not capable of storing multiple account_ids for a single UserId.) In order to do this, the system would add an entry to the User Table, where the new UserId would map to the same account as the original UserId.
  • A user can still change their UserId. (Add an additional UserId, then remove the original UserId.)
An extra, optional feature is "cls/grantAccess" grant_user_access. An RP website can implement this whenever they get around to it. (It requires a more advanced *User Table*.)

This specification already requires that a UserId and account_id be different. This is because users must be allowed to to change their UserId. (A UserId can be lost, compromised, etc.) If the UserId were used as the account_id, then when a UserId is changed, then the account_id would also change. This is a very bad idea. And would have many complications and edge cases. Because of this, using a UserId as the account_id is not advised. It is a basic requirement that the account_id be independent of any UserId.

RP websites should already be using a mapping, from a "username" to an account_id. At least, this is the way that usernames should currently work at the RP website. (This assumes that the website implemented usernames correctly, and it did not use the "username" as the account_id.) Usernames are just another type of UserId. The username to account_id mapping could be either one-to-one or one-to-many, both will work. However, using the one-to-many mapping is strongly encouraged, as it will allow Account Sharing. Note that it is possible for RP websites to use both usernames and CAPIS UserIds concurrently. They are just two different types of UserId, mapping to the same account. Therefore, a CAPIS UserId database table can be used as a drop-in replacement, or an addition to, a username and password setup.

In order for an RP website to implement "grant_user_access", it must do the following.
  • Update the User Table to support a "one-to-many" relationship between UserIds and account_ids.
  • Implement some sort of *account switching* in its web pages. So that users can access the different accounts they have access to.
  • Provide a way for account owners to add additional "authorized users". Probably allow them to create invitation codes.
  • Provide a way for users to be added to an existing account. i.e. A way for users to use an invitation code and be added as an "authorized user" to an existing account.

    This could be done by user IDs that are unknown to the website (and have no account), or by user IDs that already have access to an account at the website. (They could be the owner, or an "authorized user" of the account.)

How to upgrade the User Table.
  • The *User Table* must be made "one-to-many", instead of one-to-one. A single UserId can be used to access multiple accounts.
  • The "User Table" needs to hold all the information about the UserId. For example, it needs to hold the public key, the backup key, and all status codes. (if the UserId is locked or compromised. etc.) Therefore, the UserId information must be moved from the account table to the User Table.
  • The User Table must have a *permission level* or *account_permission_role* for each UserId and account_id combination. Possible levels could include: owner, full, read-only, restricted1, restricted2, none.

Some Ideas for Possible Capis Login Additional Features

Features
  • Temporary access on any computer. The Login Manager can temporarily authenticate a computer for 2 hours. (login and passwords will expire after 2 hours)
  • Automated public key change (i.e. Automated password change for a website.)
  • Can enable multi-factor login
  • Can mark a device as "trusted", and use single login (Not multi-factor login)
  • A
  • A

For Automatic public key change, the changed password (private key) is encrypted locally (on the user's computer) before syncing with the user's password manager, never allowing the password manager to access the raw data. Just like all other data on the user's Password Manager account.

Can mark a device as "trusted". A random, unique identifier is created for that device. It is then encrypted using Windows "crypt protect data" functions. It encrypts it based on the user's credentials. So that another user of the device cannot decrypt it. A hash of the ID is stored in the Password Manager server database. During login, the ID is decrypted on the device, a hash is created, and sent to the login server.

For mobile devices, a randomly generated id is stored in secure phone storage.

CapisLogin User Authentication Flow - Detailed walkthrough

Here are the detailed steps. (For example, in order for a user to sign-in.)

  1. The browser will retrieve the "RP Config Document" for the website. (via HTTPS)
    In the document is the list of RP Service Descriptors. The browser will find the appropriate one. This descriptor describes what types of authentication the website supports, i.e. what it needs to automatically log the user into the website. The descriptor should provide as much information as possible, in order to narrow the choice of the user's credentials.
  2. The browser starts the Proof Creation Algorithm in an attempt to create a "proof of identity". See API function CapisLogin.buildServiceRequest(opId, callOptions).
    The browser tries to create a "proof of identity" that meets the requirements of the RP's "authentication service descriptor". This process uses the internal API. This process is done mostly automatically, but the browser may require the user to (1) select which UserId to use, and/or (2) login to the identity provider. (If the UserId is a "Locked Id" then it uses a "Multi-Site UserId Credential Verification Rule". This may exist in an "UserId certificate". If the "UserId certificate" stored in the browser has expired, then the user must login to the IdP.) Note that the "proof creation" process may fail, particularly if the browser does not have credentials of a type required by the website.
  3. The browser decides which UserLogin to use.
    The browser may have a user setting telling it which UserLogin to use in which situation. Or, the UserLogin to use can be obtained from the data that was stored locally (in cookies, in local storage, in the password manager) after a previous registration or UserLogin import, etc. Or it can be determined by other means such as prompting the user which ID to use. This step is encapsulated in the API step CapisLogin.buildServiceRequest.
  4. The browser creates a CLS Request.
    A CLS Request typically contains a single JSON object. The browser puts all the data to be sent to the RP into the object. The "request_object" contains various request properties. These include: the "proof of identity" (a.k.a. the payload"), the user_id_certificate_chain, and the uac_registration, which details desired changes to the Credential Verification Rule stored by the RP. It also includes whatever else is needed to perform the serviceOp. is sometimes needed. (For example, a Set Active Credentials (i.e. public key change request) needs a new public key, "uac_registration", object. etc.)
    The browser extracts the Trigger Configuration Options, from the RP Service Trigger (i.e. from the HTML anchor that the user clicked). It then creates the CapisAPI.callOptions argument from the values. It also copies some of the values into the CLS Request. (For example, the "serviceOp" and "redirectUri" configuration properties are put into the CLS Request as "payload.reqOp" and "payload.redirectUri" properties, respectively.)
    From the Client Configuration Options, the "challenge" property is copied into the "payload.challenge" field in the CLS Request.
  5. The browser sends the "service request" to the "RP service endpoint".
    All the request data is combined into a single JSON object. (A CLS Request "request_object") This includes all request options and the "proof of identity". The request is sent to the "RP service endpoint" in whatever manner the RP designated in the RP Config Document. See CLS Request Detail.
  6. The RP website receives the CLS Request. (i.e. the HTTP POST)
    The RP reads the "service request" and attempts to verify the "proof of identity". If it is valid, the website performs the requested serviceOp. (e.g. logs the user in.) It sends a CLS Response (via HTTP) to the browser stating what happened. (If the serviceOp succeeded or failed.) If the proof is not valid, the RP can return an error. Otherwise the RP can return a success code. In addition to the "success code", the RP can return a redirectUri, or it can direct the browser to refresh the current page or part of the page. (So that the "cls/login" anchor becomes a "cls/logout" anchor. etc.) The RP can simply return a simple "success" status by itself, without any extra data. The simple "success" status will cause the browser to do the default behavior, to refresh the current page.
  7. The browser receives the CLS Response.
    If it is a "success" response, the browser usually just refreshes the page. This will cause the page to refresh, and to display any previously restricted material. If the response was "failure", then the browser will display the HTML document delivered with the response. (The document returned with a "failure" code should be an HTML document containing some error message to the user.)

The serviceOp property Detail

CAPIS opId Detail

RP services can perform various operations. The Operation to be performed by the Service is specified in the Operation Identifier. (The "opId".) Each protocol defines it's own List of valid Operation Identifiers. (See CLS Operation List.)

The "serviceOp" property contains the "Service Protocol Id" before the slash, and the opId after the slash. (The Protocol ID corresponds to the "serviceDesc.protocol" in the RP Service Descriptor.)

For example, if the serviceOp is "cls/login", then the service protocol is "cls", and the opId is "login".
The service method may be one of the CLS Operation List values.
Example Anchor:
<a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>

CLS OpId Detail

A Capis Login Service "Operation Id" is an action that the browser requests the RP to perform. The Method value is specified by the browser and sent to the RP service endpoint in the CLS Request. In other words, the Method is the operation that the browser asks the RP to perform. The currently spported values are listed in the CLS Operation List.

The opId value is usually specified in the "serviceOp" property. This is in the "capis-config" attribute of an CAPIS HTML Element. (Either a CAPIS Anchor or a CAPIS Form.) The opId value is sent to the RP in the CLS Request. (The serviceOp value is copied into the reqOp property.)

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>
...
<a href="/_capis/fallback/setActiveCredentials.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/setActiveCredentials" '>Set Active Credentials</a>

CLS Operation List

The list of User Authentication serviceOp values:

These values can be sent to the RP in the CLS Request reqOp property. The value is typically specified in the "serviceOp" property. (In the "capis-config" attribute of an CAPIS HTML Element. Usually either CAPIS Anchor or CAPIS Form.)

CLS OpId: Value "login"

Performs a login operation. Sends a login request and a proof of identity to the RP.

Example Anchor:
<a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>

Tells the browser to create a "login" CLS Request and send it to the RP. The request will contain a "cls/login" reqOp.

The browser will select a UserId to login with, and send a proof of identity to the RP in the service request. The request tells the RP to login the user with the supplied information.

CLS OpId: Value "logout"

Performs a logout operation. Sends a logout request to the RP.

Example Anchor:
<a href="/_capis/fallback/logout.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/logout", "redirectUri":"/some/path/page.html" '>Logout</a>

Tells the browser to create a "logout" CLS Request and send it to the RP. The request will contain a "cls/logout" reqOp.

The "cls/logout" serviceOp in the request tells the RP to log the user out.

The RP should tear down the user's session or redirect the user. The RP needs to at least refresh the page to remove sensitive information.

CLS OpId: Value "proveUserPresence"

Performs a "user-presence" operation. Sends proof of user presence to the RP. (force authentication)

Example Anchor:
<a href="/_capis/fallback/proveUserPresence.html", rel="capis-trigger" capis-config=' "serviceOp":"cls/proveUserPresence", "redirectUri":"/some/path/page.html" '>Confirm your presence to see the next page</a>

Tells the browser to create a "proveUserPresence" CLS Request and send it to the RP. The request will contain a "cls/proveUserPresence" reqOp.

Tells the browser to send proof of user presence to the RP. Similar to a login. The proof requires user interaction. (force authentication)

This is to prove to the RP that the user is currently using the computer or device. (The user has to touch something or type something.) This takes the place of an RP asking the user to type in their password again, before displaying sensitive information such as credit card numbers. The RP can require proof of user presence at any time.

When sent to an RP inside a CLS Request, the "cls/proveUserPresence" serviceOp tells the RP to confirm the "proof of user-presence" results and then to re-authenticate the user. (forced authentication)

The RP may require that user presence be checked before displaying sensitive information. (Before allowing credit card numbers to be changed, etc.) To force the user to confirm their presence, the RP can omit the sensitive data on the page, until the user presence is proved, and then refresh the page or a part of the page.

Proof of user presence is generated by the browser, or by an "authentication device". Such as a Login Manager. This has the device authenticate the user presence through some sort of signature or biometric, etc. The proof contains a timestamp when the user presence was generated. The same proof of user presence can be used at multiple RPs. An RP should generally accept a proof of user presence if the timestamp is less than 2 minutes old.

Possible methods of checking for user presence

A list of all possible ways to prove user presence.

CLS OpId: Value "createUserLogin"

Performs a "User Login creation" operation. Sends the result to the RP.

Tells the browser to perform a "create user login" operation. Send the result to the RP. (This command is alternately known as "sign-up". From "login/sign-up".)

The request may contain the new "UserLogin" information. (The RP can supply a username, or the browser can create one.)

Example Anchor:
<a href="/_capis/fallback/createUserLogin.html", rel="capis-trigger" capis-config=' "serviceOp":"cls/createUserLogin" '>Sign Up/Register</a>

IMPORTANT: The "cls/createUserLogin" serviceOp value should generally not be used in HTML pages. The "createUserLogin" value should generally only be used in the reqOp property of a CLS Request. In HTML pages, it is almost always a better idea to use the "cls/login" value. This is because using the "cls/login" serviceOp value can cause EITHER the "login" or the "createUserLogin" value in the reqOp property of the CLS Request. Using a "cls/login" serviceOp value leaves the decision of which action to perform up to the browser and/or the user. (Using "cls/createUserLogin" in an HTML page removes the choice of "login" or "createUserLogin" from the popup shown to the user.)

Using the "cls/login" serviceOp value gives the browser and/or the user the opportunity to *decide* what to do. To perform a login or to create a new user login. For example, the browser or the user can check if the Login Manager has no stored credentials for the RP, or the user can simply decide to create a new user login, instead of using an existing user login.

When sent to an RP inside a CLS Request, the "cls/createUserLogin" serviceOp tells the RP to create a new account for the user, with the supplied information. (Tells it to create a new account using the supplied UserId and the Credential Verification Rule.) (In the future, the user should be able to login with the supplied UserId and appropriate credentials.)

When used as an serviceOp in an HTML anchor, it tells the browser to send the RP a "cls/createUserLogin" package.

The "userIdRules.userIdTypes" property of a service limits what type of identifier can be used to create an account. (e.g. "single_site_userId", "ciq:C:B1:9:ri", etc.) The property is in the "RP Service Descriptor".

See the full Login Method List.

In order to create an account, the browser must use one of the serviceDesc.userIdRules createMethods.

CLS OpId: Value "addHoldRestriction"

Disables the user's account at the RP. (For security)

Example Anchor:
<a href="/_capis/fallback/addHoldRestriction.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/addHoldRestriction", "redirectUri":"/some/path/page.html" '>Place Hold</a>

Tells the browser to create a "addHoldRestriction" CLS Request and send it to the RP. The request will contain a "cls/addHoldRestriction" reqOp.

Tells the browser to send a "cls/addHoldRestriction" request to the RP. Tells the RP to disable logins by the user id. The RP should not allow a login from the UserId until the hold has been removed. ("removeHoldRestriction") This can be activated when the user suspects that their password (etc.) has been compromised. Note that this only disables the UserId, it does not necessarily lock or disable the account. (There can be other UserIds that can log into the account.)

CLS OpId: Value "removeHoldRestriction"

Re-enables the user's account at the RP.

Example Anchor:
<a href="/_capis/fallback/removeHoldRestriction.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/removeHoldRestriction", "redirectUri":"/some/path/page.html" '>Remove Hold</a>

Tells the browser to create a "removeHoldRestriction" CLS Request and send it to the RP. The request will contain a "cls/removeHoldRestriction" reqOp.

Tells the browser to send an "cls/removeHoldRestriction" request to the RP. Tells the RP to remove the hold on the UserId. This requires sending the RP a special code, that is checked against the "backup_credentials ("bkcr")" stored by the RP.

CLS OpId: Value "signData"

Signs a form. Sends a "signed-form" request to the RP. Only usable on forms.

Tells the browser to sign the form. Send a "signed-form" request to the RP. Only usable on forms.

When sent to an RP inside a CLS Request, the "cls/signData" serviceOp tells the RP to receive a signed form. (That the sent value is a signed form.) (See Form Signing)

When used as an serviceOp in an CAPIS HTML Element, tells the browser to send the RP a "signed form" package. Tells the browser that the RP requires the form signed. The "cls/signData" value can only be used on a form (not an anchor or link).

CLS OpId: Value "setActiveCredentials"

Also known as Set User Credential Verification Rules.

Changes the user's login credentials. (i.e. passwords or public keys, etc.)

Example Anchor:
<a href="/_capis/fallback/setActiveCredentials.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/setActiveCredentials", "redirectUri":"/some/path/page.html" '>Set Active Credentials</a>

Tells the browser to create a "setActiveCredentials" CLS Request and send it to the RP. The request will contain a "cls/setActiveCredentials" reqOp.

This function lets the user change their password or public key. It is analogous to "change user password". If the user's private key is compromised, has a weakness, etc. the Credential Verification Rule can be changed.

The browser will create a CLS Request that asks the RP to make changes to the Credential Verification Rules that it stores for the user. The command can add (register) new Credential Verification Data and select which existing CVR are active. (From an existing list.) The request contains a "uac_registration" section. The "uac" section contains two lists, "existing" and "new". The first is a list of ids of existing Credential Verification Rules that should be de-activated (or deleted). The second is a list of new Credential Verification Rules that should be added.

Each of the items in the list of "new CVR" must have a "credentialVRItem.value".

The "setActiveCredentials" opId cannot be used to change the UserId. It can only change the Credential Verification Rule. In order to change the UserId, use "cls/changeUserId".

Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "setActiveCredentials", "sub": "cls/setActiveCredentials", "iat": 1503971280, // issuedAt timestamp "exp": 1533064012, // expiresAt timestamp "aud": "RP_example.com", // the audience "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", // nonce value "nit": 1533064012, // nonceIssueTime "uid": { "raw": "ciq:C:A:3:X0s5eA:Aq", // The ciq UserId "usk": "q3jC9-h" }, "user_auth_method": "stored_cred", "redirectUri": "/some/path/page.html", "useCount": 42,
/* The user_id_certificate_chain is absent when using the "stored_cred" uauth_method. // user_id_certificate_chain "uic_chain": [ {"uic.format":"JWS", "uic.csvm":"YY", "ucv": { "payload":"82h7vb...", "signatures": [...] }} ], */
// crProofSection. "crProofSection": { "uid": { "raw2": "ciq:C:B1:2:xxxxxxxx", // The ciq UserId }, "uapCounter": 42, "cpl": [ { "cpid": "cd2", "cpt": "pubkey", "cpf": "TBD-CPF", // "credentialProofItem.format": "TBD-CPF" (not necessary. The default is "TBD-CPF".) "cpv": "mmmm" // base64url encoded JWT or signature. } ] }, // uac_registration. Required for "createUserLogin" and "setActiveCredentials" reqOp. "uac": { "backup_credentials": [ { "cvid": "cd-3", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { ... } } ], "cvrList": [ { "cvid": "cd10", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { "kty": "EC", "kid": "cd10", // "kid" is REQUIRED. Is the same as the "cvid". "crv": "P-256", "ext":true, "key_ops": ["verify"], "x": "5sy3ogiqTrlC_FF7aOdCq7cNFsN2nbrH4xQmNCCBtso", "y": "ctK7P_LU-SQPf-ejkmC1JYzm7S5N0B6ZX5rwOQWzuv8" } } ] } };

When using "cls/setActiveCredentials", the UserId sent in both the tokens must match the existing UserId stored by the server (the RP).

Note: The "credentialProofItem.value" value (usually a JWT) and the "signatures" are verified by using the Credential Verification Rule (CVR) stored at the RP. (i.e. the stored_cred.) (i.e. The service request is signed with the existing CVR.)

Some of the known Credential Verification Rule (CVR) are a public key fingerprint, or storing the entire public key.

The RP can create a "UserLogin" with one or more CVR. It doesn't matter whether the account uses a "Locked Id" or a "Single-site UserId". (Such as the username in a regular username and password.) Both types of accounts can potentially have CVR.) Or an account can be created without any CVR at all. In this case, such an account must use a Locked Id. As without a CVR, the "proof of ownership" of the Locked Id is the only way a user can authenticate themselves and login to the account. See the full "Login Method List".

Depending on what abilities the RP offers, a user can:
{
  "id": "service_1",
  "protocol": "capis_login_service",
  "endpoints": [
    { "id":"endpoint_1", "sUri":"/_capis/cls/serviceCall", "request_format":"JWS" }
  ],
  "userIdRules": {
    "userIdTypes": ["single_site_userId", "ciq:C:B1:9:ri"],
    "createMethods": ["assigned_ulc", "claim_ms_ulc"]
  },
  "supported": {
    "userAuthScheme": {"methods":["stored_cred", "only_MSUID"]},
    "supported.uic.csvm": ["basic1", "basic2"],
    "credentialReg": {
      "passwordTypes": [{"name":"password_s1", "maxLength":14, "storageQuantity":"1"}],
      "publicKeyTypes": [{"name":"pubkey_s1", "JWA_alg":"ES256", "storageQuantity":"1"}]
      // Note that "publicKeyTypes": [{"name":"pubkey_s1", "JWA_alg":"ES256", "storageQuantity":"1"}] is the default.
    }
  },
  "requirement_section": {}
}
The HTML anchor:
<a href="/_capis/fallback/setActiveCredentials.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/setActiveCredentials", "redirectUri":"/some/path/page.html" '>Change your public key</a>
Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "setActiveCredentials", "sub": "cls/setActiveCredentials", "iat": 1503971280, // issuedAt timestamp "exp": 1533064012, // expiresAt timestamp "aud": "RP_example.com", // the audience "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", // nonce value "nit": 1533064012, // nonceIssueTime "uid": { "raw": "ciq:C:A:3:X0s5eA:Aq", // The ciq UserId "usk": "q3jC9-h" }, "user_auth_method": "stored_cred", "redirectUri": "/some/path/page.html", "useCount": 42,
/* The user_id_certificate_chain is absent when using the "stored_cred" uauth_method. // user_id_certificate_chain "uic_chain": [ {"uic.format":"JWS", "uic.csvm":"YY", "ucv": { "payload":"82h7vb...", "signatures": [...] }} ], */
// crProofSection. "crProofSection": { "uid": { "raw2": "ciq:C:B1:2:xxxxxxxx", // The ciq UserId }, "uapCounter": 42, "cpl": [ { "cpid": "cd2", "cpt": "pubkey", "cpf": "TBD-CPF", // "credentialProofItem.format": "TBD-CPF" (not necessary. The default is "TBD-CPF".) "cpv": "mmmm" // base64url encoded JWT or signature. } ] }, // uac_registration. Required for "createUserLogin" and "setActiveCredentials" reqOp. "uac": { "backup_credentials": [ { "cvid": "cd-3", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { ... } } ], "cvrList": [ { "cvid": "cd10", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { "kty": "EC", "kid": "cd10", // "kid" is REQUIRED. Is the same as the "cvid". "crv": "P-256", "ext":true, "key_ops": ["verify"], "x": "5sy3ogiqTrlC_FF7aOdCq7cNFsN2nbrH4xQmNCCBtso", "y": "ctK7P_LU-SQPf-ejkmC1JYzm7S5N0B6ZX5rwOQWzuv8" } } ] } }; let CLS Request = { "JWS": { "payload": BASE64URL(UTF8(payload_unencoded)), "signatures": [ { "protected": "eyJhbGciOiJFUzI1NiJ9", // protected_header = {"alg":"ES256", "sct":192} "header": { "kid": "cd1", "kid2": "e9bc097a-ce51-4036-9562-d2ade882db0d" // "kid": "userIdPK" // "userIdPK" means the public key is in "uid". }, "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga" } ] } }

The JWT must be signed with the "current" public key.

Note that changing the "Credential Verification Rule" uses the same URL as the site login. This is intentional, so that automated tools can change the user's public key (or other CVR) on multiple sites easily. A browser can remember the URLs used to login to RPs previously. The "remembered RP endpoints" can be called sequentially. With the old CVR and the new CVR in order to replace the CVR stored for the Locked Id at every RP.

CLS OpId: Value "changeUserId"

Changes the UserId in a single operation.

Example Anchor:
<a href="/_capis/fallback/changeUserId.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/changeUserId", "redirectUri":"/some/path/page.html" '>Change UserId</a>

Tells the browser to create a "changeUserId" CLS Request and send it to the RP. The request will contain a "cls/changeUserId" reqOp, and a "uac_registration" section. It will contain the user's selected option to create the new user id. It includes the Credential Verification Rules for the new UserId.

This function lets the user change their UserId. It is analogous to "change username". This command can be used if the UserId is ever compromised, stolen, copied, etc.

The user can also change their UserId the long way. By adding a new UserId to the account, as an authorized user. Then changing the "owner" of the account to the new UserId. And then removing the original UserId.

CLS OpId: Value "grantAccess"

Grants another UserId access to the user's account at the RP. Select a (different) UserId for use with the account. And an account_permission_role. Send to the RP.

Example Anchor:
<a href="/_capis/fallback/grantAccess.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/grantAccess", "redirectUri":"/some/path/page.html" '>Grant Access</a>

Tells the browser to create a "grantAccess" CLS Request and send it to the RP. The request will contain a "cls/grantAccess" reqOp and a "grant_user_access" property.

This is how the RP implements the "Account Sharing" feature. Upon activation, the browser creates a CLS Request that contains the "grant_user_access" property, and sends it to the RP.

The CLS Request tells the RP to give the specified UserId certain access rights to the account. Account owners MUST have an AUTOMATED way of ADDING a UserId to their account, in order to change their own UserId. (Because a UserId or a "UserLogin" may be compromised.)

Grants or changes the level of account access given to another UserId. The other UserId may be a person or a service. Non-person users can be called "robot" users. The new UserId may be an account the user has at a different RP. Such as an aggregator account, etc.

The "cls/grantAccess" API expands on the API to allow a UserId to add and remove other UserIds from their account. It goes one step further and also assigns an "account_permission_role" to each added UserId. The basic account_permission_roles should exist at every RP. These are "owner", "full" and "none". RPs can optionally implement other account_permission_roles.

The account_permission_roles are, from highest to lowest, owner, full, manager, read-only, restricted2, restricted1, none. Users with higher account_permission_roles cannot be modified by users with lower account_permission_roles. (A user with "full" access cannot be modified by a user with "manager" access, or any lower access.)

The highest account_permission_role is "owner". An "owner" has complete, unrestricted access to everything, and can make any changes. A user with "full" access has almost the same account permissions as an owner (i.e. the account_permission_role), except that he cannot make changes to "owners". A "full" user has full account access and can add, remove and modify most authorized users, but cannot make any changes to users that have "owner" access. A user with "account-only" access can read and change all account settings, (including billing information) but cannot add, remove or modify users. In comparison, a user with "full" account access can also modify other user accounts (but not "owners").

The "none" account_permission_role is used to turn off the account access of a user ID, without removing the user ID from the account. Example: temporarily suspend access of a child, student, employee, or group member, etc. (This can be done as a type of punishment or as a response to a perceived security threat.) The "none" level is also the default level for all pending "authorized users". That is, when an "invitation code" is used by a user ID to add themselves as an "authorized user" to an existing account, those user IDs should have (1) a "pending" status, and (2) an account_permission_role of "none". A manager must explicitly change the account_permission_role of "pending" user IDs. By default they are "none".

The "account_permission_role" to give the other UserId must be specified. For example: (none, limited, read-only, manager, full) Only the "none" and "full" levels are required. The highest account_permission_role is "full". The "full" level is even higher than any "manager" account_permission_role, as "full" access only gives the UserId **access**, it usually does not include the ability to change account access of other UserIds. The "full" account_permission_role may be assigned when the account owner wants to change their UserId, and wants to grant the new "UserId" full account control.

A UserId cannot grant another UserId greater access than it has itself. Additionally, an RP can choose to restrict the "cls/grantAccess" ability to only certain users. An RP can limit it to only a manager of the account (or even to an "owner"). So only a manager of an account can change the access rights of any other UserId.

An RP only needs to implement 2 parts of this API. The account_permission_roles "owner" and "none". In other words, granting a UserId all account access, and revoking all account access from a UserId. All other account_permission_roles are optional.

OLD SPECIFICATION. These are the two abilities needed to change the account owner's UserId. (The account owner can grant the new UserId access, then login as the new UserId and revoke the old UserId access.) The account owner MUST have an AUTOMATED way of changing their UserId. So that the owner does not have to log in to every RP website to change their UserId. Instead, a script can be run to change the UserId at every RP. However, the RP SHOULD "lock" this feature and mandate additional verification. For example, it can send the account owner an email to verify that they want to grant "owner" access to the other UserIds. An RP may choose to implement additional account_permission_roles other than "owner" and "none", or it may implement such levels through some other interface. (For example, the RP can require the owner to use an HTML page, etc. to grant account access.)

An account MUST have at least one "owner". The "grantAccess" command must NOT reduce access of a UserId if that UserId is the only "owner" on the account. Such an attempt will result in an error.

This serviceOp is usually not applied to an HTML anchor by the RP. It is usually only used by the browser to tell the RP what to do.

Works with the "account_permission_role" option. Can choose to grant a UserId less than "owner" access.

For example: a mother may give "read-only access" to her music account to her daughter. Such access SHOULD not allow the daughter to access credit card information or make any purchases. If the daughter performs "cls/grantAccess", nothing will happen to the mother's account, because the daughter does not have the ability to "cls/grantAccess" to the mother's account to other UserIds.

The "new UserId" cannot be the same as the current UserId. This command can be locked for safety purposes. It may need an email verification, etc. This is also the first step in changing the UserId of the account owner. (The username the owner logs in as at the RP.)

CAPIS HTML Element detail

This specification defines a few new CAPIS HTML elements. (These are actually existing HTML elements with a few new HTML attributes.)

List of CAPIS HTML Elements.

These elements allow RPs to embed data about RP services within HTML markup. (User authentication is one such service.) RP websites should modify their HTML pages to use the new CAPIS Link and CAPIS Anchor instead of a login form. These HTML elements have a few new HTML attributes. The attributes are rel="capis-base" and capis-config="...". The "capis-config" attribute contains a JSON-style list of name-value pairs. These are used as RP Configuration Options. RP websites can use this attribute to give the browser additional data or instructions. Such as user authentication information. Note that using the new type of HTML element does not require javascript. The RP does not have to include any javascript code in its web pages, and the browser is not required to have javascript enabled for the RP.

The CAPIS Link HTML Element is the primary means for RPs to communicate user authentication information to browsers within HTML markup. A CAPIS compliant HTML page MUST have a proper CAPIS Link HTML Element in it. The CAPIS Anchor and CAPIS Form HTML elements are secondary means, and are optional. They are designed to be used in conjunction with the CAPIS Link HTML Element. As a result of their secondary nature, there are only a few "capis-config" properties allowed in an anchor and form. These are the CLS TriggerConfig properties. (The CAPIS Anchor allows the "serviceOp" and the "redirectUri" properties.)

A CAPIS compliant HTML page MUST have a CAPIS Link HTML Element in it. The purpose is to allow the browser, in the future, to use the hidden HTML element to display the user authentication information in the browser chrome. (i.e. The RP login status and command buttons.) The items do not have to be visible in the HTML page at all. For example, the browser chrome can contain a "login" button, and a "logoutAll" button, etc. Alternativly, the browser chrome can contain a combined "login/logout" button. It would track the login state at the RP, and change its label and serviceOp between "login" and "logout".

The CAPIS HTML Elements behave differently than normal. For example, if a CAPIS Anchor is clicked, browsers that understand this specification will perform the RP Service Invocation Process. (See the CAPIS Service Invocation Flow.) (i.e. The browser will perform the CapisControl.activateTrigger.) The browser will not use the "href" attribute of the CAPIS Anchor HTML Elements. The "href" attribute is used exclusively as a "fallback" behavior. Only older browsers that do not understand CAPIS will use it. (i.e. If the browser does not understand the new attribute rel="capis-trigger".)

In order to support older browsers, the HTML pages at the fallback URLs will need to contain traditional login forms, etc. (Similarly, the CAPIS Form uses the "action" attribute as a fallback behavior. The CAPIS Link HTML Element uses its "href" attribute to point to the RP Config Document.)

Examples of CAPIS HTML Elements:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>
...
<a href="/_capis/fallback/login.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/login" '>Login</a>
...
<a href="/_capis/fallback/logout.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/logout" '>Log OUT</a>
...
<a href="/_capis/fallback/proveUserPresence.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/proveUserPresence" '>Confirm my presence</a>
...
<a href="/_capis/fallback/setActiveCredentials.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/setActiveCredentials" '>Set Active Credentials</a>
...
<form action="/_capis/fallback/signUp.html" handling="capis-trigger"
 capis-config=' "serviceOp":"cls/createUserLogin" ' onsubmit="return validateForm1()">
...
</form>

Using the (rel="capis-trigger") attribute does two things. It marks the HTML element as performing a CAPIS Trigger Behavior, and it causes the element to behave differently. The elements will perform a special CAPIS Trigger Behavior instead of their normal behavior. Clicking on a CAPIS Anchor HTML Element SHOULD NOT cause the browser to follow the href value. (i.e. To send an HTTP GET command to the "href" URI in the anchor.) Instead, it should cause the browser to retrieve the RP Config Document, and perform the serviceOp property specified in the "capis-config" attribute. For user authentication, this will send a CLS Request (via an HTTP POST) to the "RP service endpoint" specified in the RP Config Document.

The "CAPIS Anchors" and CAPIS Forms SHOULD NOT use their "href" and "action" attributes, respectively. Because of this, these attributes can instead be used as a trap to detect older browsers that do not support this specification. The URI used in the "href" attribute should link to an error page or a fallback operation at the RP website. (Or some other website the RP trusts to do the fallback operation.) The web service at the linked URI could attempt an alternative login operation, or display an error message to the user. Such an error message may be something like: "Your browser does not support the CAPIS specification. Please do xyz."

CAPIS HTML Attributes

This specification defines a few new HTML attributes. They can be applied to the anchor, form and link elements. (To create a CAPIS Link HTML Element.)

List of CAPIS HTML attributes.

Currently, only the anchor, form and link HTML elements can be marked as CAPIS HTML Elements. The CAPIS Anchor and CAPIS Link element use a special value for the "rel" attribute, (rel="capis-base"), while the CAPIS Form element uses the "handling" attribute, (handling="capis-trigger").

HTML elements that are "marked" with the special HTML attribute will perform a special behavior, the CAPIS Trigger Behavior, instead of its normal behavior. These HTML elements DO NOT use their "href" or "action" attributes. (i.e. A CAPIS Anchor will not use the "href" attribute and will not perform a web page redirect. A CAPIS Form will not use the "action" attribute and will not perform a regular form submission.) Developers should set these attributes to an error page or a secondary "fallback" login behavior. This will detect older browsers that do not support CAPIS HTML Elements.

Examples of CAPIS HTML Elements:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>
...
<a href="/_capis/fallback/login.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/login" '>Login</a>
...
<form action="/_capis/fallback/signUp.html" handling="capis-trigger"
 capis-config=' "serviceOp":"cls/createUserLogin" ' onsubmit="return validateForm1()">
...
</form>

CAPIS Anchor HTML Element

An HTML Anchor Element that has the 'rel="capis-trigger"' attribute. It can contain Trigger Configuration Options. These are used for the "RP Service Invocation Process".

CAPIS Anchor HTML Element - Attribute: rel="capis-trigger"

rel="capis-trigger"
Used on CAPIS Anchor HTML elements. It marks the element as being one of the "CAPIS HTML Elements". It marks the element as performing a CAPIS Trigger Behavior. This overrides its normal behavior.

CAPIS Anchor HTML Element - Attribute: href

href="url"

The href attribute is used exclusively as a fallback for older browsers that do not understand CAPIS. Used on CAPIS Anchor HTML elements.

The CAPIS HTML Elements behave differently than normal. For example, if a CAPIS Anchor is clicked, browsers that understand this specification will perform the RP Service Invocation Process. (See the CAPIS Service Invocation Flow.) (i.e. The browser will perform the CapisControl.activateTrigger.) The browser will not use the "href" attribute of the CAPIS Anchor HTML Elements. The "href" attribute is used exclusively as a "fallback" behavior. Only older browsers that do not understand CAPIS will use it. (i.e. If the browser does not understand the new attribute rel="capis-trigger".)

It will perform a CAPIS Trigger Behavior. This overrides its normal behavior.

<a href="/_capis/fallback/login.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>

CAPIS Anchor HTML Element - Attribute: capis-config (longName: "fubar")

Type JSON-PL. Required.

Contains Trigger Configuration Options. (A JSON-style list of name-value pairs.) Used on CAPIS Anchor HTML elements.

The capis-config attribute is REQUIRED if the HTML element has the rel="capis-trigger" attribute. Because the anchor MUST contain Trigger Configuration Options, which MUST contain the serviceOp property.

Example Anchor:
<a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp": "cls/login", "redirectUri": "/some/path/page.html" '>Login</a>

CAPIS Form HTML Element

An HTML Form Element that has the 'rel="capis-trigger"' attribute. It can contain Trigger Configuration Options. These are used for the "RP Service Invocation Process".

CAPIS Form HTML Element - Attribute: handling="capis-trigger"

handling="capis-trigger"
Used on CAPIS Form HTML elements. It marks the element as being one of the "CAPIS HTML Elements". It marks the element as performing a CAPIS Trigger Behavior. This overrides its normal behavior.

CAPIS Form HTML Element - Attribute: action

action="url"
Same as the Anchor href attribute. It's used exclusively as a fallback for older browsers that do not understand CAPIS.
<form action="/_capis/fallback/signForm.html" handling="capis-trigger"
 capis-config=' "serviceOp":"cls/signData" '>
  <input type="text" name="first_name" placeholder="Enter your first name" />
  <input type="text" name="user_email" placeholder="Enter your email address" />
  <input type="submit" value="Sign and Submit the Form" />
</form>

CAPIS Form HTML Element - Attribute: capis-config

Type JSON-PL. Required.

Contains Trigger Configuration Options. (A JSON-style list of name-value pairs.) Used on CAPIS Form HTML elements.

The capis-config attribute is REQUIRED if the HTML element has the rel="capis-trigger" attribute. Because the form MUST contain Trigger Configuration Options, which MUST contain the serviceOp property.

Example Form:
<form action="/_capis/fallback/signUp.html" handling="capis-trigger" capis-config=' "serviceOp":"cls/createUserLogin" ' onsubmit="return validateForm1()"> ... </form>

Default Location of the CAPIS Document

The default location of the RP Config Document is to use the "well-known" URI.

The "well-known" URI of the RP Config Document is created by appending "/.well-known/capis_config.json" to the HTTPS version of the page origin. Example: "https://RP_example.com:port/.well-known/capis_config.json" (Note that the "well-known" URI uses "https", and can have a port number.)

The default location is used if the "href" attribute of the CAPIS Link HTML element is missing or invalid.

Note that if a "capisDocUri" is used that does not have a path component, (does not contain anything after the domain name. Not even a "/" character.), then the capisDocUri that is used also appends the "/.well-known/capis_config.json" string.

See the other CAPIS specification default values.

User Login Detail

A User Login is the data needed for a user to login to an RP. (i.e. To authenticate a user to an RP.) It is also a name for the stored "user identity" at the RP. (A "user identity" may not be the same as an "account" at the RP, as multiple users may be able to log into a single account. See Account Sharing.) In general, it is the combination of (1) a unique user identifier (i.e. a UserId) at the RP and (2) some means for the user to prove ownership of (or authorized use of) the user identifier.

A User Login has at least five types of components, although some may be omitted. (1) The RP id. (2) A user identifier. (i.e. a UserId) (3) A set of "secrets" known only to the user. (i.e. Credential Sources. Such as private keys or passwords.) (4) A set of "user secret verification data" stored by the RP. (i.e. Credential Verification Rules. A way for the RP to verify the user has the secrets.) (5) A UserId binding document (or a database entry at the RP). This associates the UserId with the "user secret verification data". Special Note, a "username and password" is a simple User Login, where the password serves as both the "secret" and the "user secret verification data". A more advanced version can also add a "backup_credential ("bkcr")" key pair, a "login counter", and a "last use timestamp". (See "UserLogin").

In order to sign-in, the user generates a "proof of identity" from their secrets, and sends the proof to the RP. The RP receives the proof, retrieves the Credential Verification Rules for the UserId (by using the binding), and then verifies the proof against the CVR.

There is a type of UserLogin, known as Federated UserId, where the RP uses an intermediary to verify the user. This intermediary is called an identity provider. This type of User Login requires that the RP trust the identity provider. With this type of User Login, the user provides some type of proof to the RP, and the RP checks that the identity provider verifies the proof. (Note that the user proof contains the UserId. Also, the UserId typically contains (or otherwise references) the domain name of the identity provider.) The user proof can be verified in 2 ways. (1) The RP submits the user proof to the identity provider, and lets the identity provider validate the proof. (This gives the UserId to the identity provider, allowing it to track when it is used, and by which RP.) Or (2) the RP can verify the user proof itself, using the identity provider's public keys, etc. (i.e. This requires that the user proof contain digital signature(s). The RP retrieves the set of public keys from the identity provider. It does not give the identity provider the UserId.) In this case, the user proof must include a document that "binds" the UserId to a set of "Credential Verification Rules". And this document must be signed by the identity provider. (It may be indirectly signed, and include a certificate chain. etc.) This document is typically a UserId certificate. It can be minutes old, or months old. It gives the RP the Credential Verification Rules, and then the RP can evaluate if the user provided proof-of-identity meets the requirements of the Credential Verification Rules.

Storing UserLogins at an RP.

An RP must store UserLogins in order to authenticate its users. An RP may store UserLogins either inside individual accounts, or outside of accounts, in a "User Table" (it may give it some other name). The downside to storing UserLogins inside accounts is: (1) A user must identify the account they are trying to access before logging in. (2) It does not allow Account Sharing. For maximum effect, the RP will need to store UserLogin information *outside of* accounts. (in a User Table inside a database, etc.) This is one way of providing two features. It provides a way for an RP to allow multiple users to access the same account, and it provides a way for an RP to allow a single user to access multiple accounts. For both of these features, each user will need their own UserId and Credential Verification Rules. Rather than storing these in multiple locations (in multiple accounts), the UserLogin can be stored in a location distinct from the accounts.

User_id Binding Method. Binding CVR to User_id

A "binding method" is a means of proving an association between a UserId and a set of Credential Verification Rules (such as public keys). It is a required part of a UserLogin. A simple example of a "binding method" is an entry in a database at the RP, where the RP stores a UserId and a list of the associated Credential Verification Rules. Another example is a UserId Binding Document.

User_id Binding Document

A small document that contains a UserId and a set of Credential Verification Rules. This associates the two items (the UserId and the various CVR) and "binds" them together. It is an example of a "binding method". In the case of such a "binding document" created by one entity and used by another, the document must contain a cryptographic signature from a reliable source, so that it cannot be faked. An example of this is a "UserId certificate", created by a Backer.

Multi-Site UserId detail

There are two main types of Locked Id, "Self-contained" and "Federated". The difference is where the lock requirements are stored. A "Self-contained UserId" contains the requirements inside itself. This is usually some sort of cryptographic key or signature. (For an example, see the "C:B1:1" ciq type.) A Federated UserId stores the lock requirements online at a third-party. At a Backer or Identity Provider

Multi-Site UserIds require cooperation from RPs. A compliant RP MUST NOT register a Locked Id to any of its users, unless the user can unlock the ID. That proves that the user satisfies the identifier's lock requirements. (i.e. An RP must not allow the creation of an account that uses a Multi-Site UserId, without verifying that the user satisfies that identifier's lock requirements.) This is the primary reason why the "type" of Multi-Site UserIds must be easy to read, and why they must be easy to distinguish from Single-site UserIds. For easy RP compliance. If an RP does not support an identifier's lock method, then the RP must not allow the use of that type of identifier. (Locked Ids could alternately be called "Multi-site UserId" or "requirements UserId", etc.)

In order to make RP compliance easier, Multi-Site UserIds MUST have an easy-to-identify "format" and "type". This makes Multi-Site UserIds easy to distinguish from Single-site UserIds. The "type" clearly identifies what type of lock the identifier employs, and the method of user-verification that it uses. The CIQ standard is one such format.

During both login and "create account" attempts, the user gives the Multi-site UserId to the RP. The RP will extract the "type ID" from inside the UserId. (If the UserId is a Federated UserId then the RP will also extract the "Backer Id".) Note that the "type ID" may be inferred from the format of the UserId. For example, an email address format will use an email address "type ID".

Then the RP will confirm that the user "owns" the UserId. For a Federated UserId, the RP will execute the Federated UV Method, and have it validate the documents provided by the user during the login attempt. Then the RP must find the Backer VM for the type ID and Backer.

If the UserId is a Self-contained User_id, then the RP will need to parse the UserId into something, or extract data from inside the UserId. (For example, it can be parsed into a public key.) The RP will then use the result to validate the user. The RP uses the "type ID" to determine what to parse the User_id into.

========

A "Federated UserId" uses some type of online host. The UserId must contain a "Backer Id" and a "registration ID". The "Backer Id" represents an organization. The "registration ID" represents the user or resource at the organization. Each Backed UserId must contain a distinct "registration ID".

A Backer must have some way to authenticate its users. It may issue a certificate or require users to login, etc. If the Backer generates a timestamped "proof of login", then all UserIds that use that Backer are "federated UserIds". A Federated UserId will issue a "user_account" or the UserId requirements that users must meet in order to use the UserId, etc. The UserId itself only needs to contain a "Backer Id" and a "registration id". For Example: an email address is a "Federated UserId". The "domain name" is the "Backer Id", and the "user account name" is the "registration id". The server running the email system (i.e. the "Backer") can be used to verify if a user has access to the UserId.)

A "Federated UserId" usually depends on the Backer continuing to behave correctly. Although, a specially designed registration systems can have UserId that only need a working Backer during their creation. But this is unusual.

This category of UserId is (1) universally unique, (2) persistent across all RP (it identifies the same user at all RP), (3) allowed access is provable, (4) its use is restricted at RPs, (5) can only be used by the "owner". RPs are required to obtain proof of ownership from a user before allowing the user to use it.

A Locked Id is capable of being used at multiple websites. However, this does not mean that it MUST be used at multiple websites. For privacy reasons, it might be preferable to use a different Locked Id at each RP website.

RPs must not register a Locked Id to any of its users, unless the user can unlock the ID. i.e. Prove he owns it. In this manner, the UserId is guaranteed to be available at an RP for the owner to use. A single user can have multiple "Locked Id". Each one can be used independently.

A "Locked Id" generally comes in one of two forms. Either the UserId contains the result of some sort of cryptographic "one-way function", (like a "public key"), or it contains the "SimpleBackerId" of the entity that created it. This allows a verifier to identify the Backer of a UserId. (The "host" can also be known as the "issuer" of the UserId.) The verifier can contact the Backer, to request that it provide some sort of additional information about the user that it issued the UserId to. The Backer can give the RP a verification requirement, such as a public key. Or the Backer can verify the user itself, and give to the RP an assertion that the user is the owner of the UserId. (This last option is typically called a "federated UserId". Where the RP must trust the "assertion" created by the "issuer" of the UserId.)

In order for "Locked Id" to work correctly, their use must be restricted at all RP. A Multi-Site UserId must never be used by anyone other than the "owner". This means that all conforming RP MUST (1) recognize Locked Id and (2) not allow the use of a Locked Id by anyone other than the owner. (i.e. An RP must not register a Locked Id to any of its users, unless the user can unlock the ID.)

In order for a "Locked Id" to work correctly, there MUST be a way for RP to verify a user's claims of owning the UserId. For Federated UserId, there must be a Backer VM for the type of federated UserId. And it must be "findable" by all RPs.

For example, a "universally unique" Federated UserId can be created by combining any "Single-site UserId" with the domain name of the RP where it is used. However, In order for those identifiers to be a Federated UserId, there must be a Backer VM for that type of federated UserId. And it must be "findable" by all RPs. If it is not "findable" by all RPs, then the UserId is not a "working" "Locked Id".

Using a Locked Id skips the hardest part of traditional User Login creation, having the user find (and remember) an unused Single-site UserId. With the traditional means of a username and password, creating an account at an RP requires the user to find an unused username at the RP.

When creating a new account with a Locked Id, the user does not have to "find an available id" at the RP, as the "UserId" is reserved for his exclusive use, at every RP. All RPs must restrict use of a Locked Id to only the party that can provide proof of ownership. Thus, a Locked Id functions as a "reserved username" at all RPs. When using a Locked Id, an account can be created automatically, without user intervention or negotiation with the RP. However, an RP SHOULD NOT automatically create an account for a Locked Id in response to a login CLS Request. (i.e. When a user tries to login with a Multi-Site UserId, and the RP has VERIFIED that the user owns the UserId, but the RP does not have an account for that UserId.) Confirmation from the user is required before User Login creation. (To prevent User Login creation due to user error. For example, if the user accidentally selected the wrong User Login to log in with, etc.) See User Login creation.

Multiple Credential Authentication

Multiple Credential Authentication is when an RP requires proof of multiple credentials in order to authenticate a user. Each credential can be of a different type. (password, private key, fingerprint, PIN, etc.)

Multiple Credential Authentication allows RPs to combine multiple authentication mechanisms to authenticate a user. Such as fingerprint + PIN. For example, a bank may want to have very strict requirements for logging in. It may want a HOTP code in addition to a regular password. Or a fingerprint in addition to both the HOTP code and password.

Note that multi-factor authentication is a subset of Multiple Credential Authentication. Each "factor" can be transmitted to the RP as a different type of credential. (Also note that 2nd factor authentication, U2F, etc. are forms of Multiple Credential Authentication.)

An RP website can store various Credential Verification Rules to authenticate a user. The RP can require multiple credentials before it will authenticate a user. (These things do not require Multiple Credential Authentication.)

Using "Multiple Credential Authentication", an RP is able to list what credentials it requires. (These credentials can be "authentication factors".) Using "Multiple Credential Authentication", the browser is able to deliver to the RP, in a single request, all the required credentials. This lets RPs create their own security requirements. They can mix different existing standards. (Or even create their own.)

Multiple Credential Authentication is implemented in the CLS Request sent from the browser to the RP. The request normally includes both (1) a signatures section (for private key signatures), and (2) a credentialProofList section (for all other types of credential proof). The "set credentials" version of the request also includes a list of Credential Verification Rules, which is used to deliver to the RP the list of Credential Verification Rules that the RP should store. Note that each credential in the list can be of a different type. And new types of credentials can be created. The only requirement is that both the RP and the Login Manager support the new credential type.

An RP can even do more complicated things, like define a set of credentials and require a minimum number of them. For example, it can require that a user provide proof of 3 out of 4 credentials in the set.

Multi-Factor Authentication

Multi-factor authentication is where an RP verifies a user's identity by requiring two or more "factors" of authentication. The three types of authentication factors are something you know, something you have, and something you are. Something you know can be something like a password or PIN. Something you have can be a mobile phone or a special USB key. And something you are can be something like your fingerprint or other biometric identifier.

"Multi-factor" authentication can be implemented by Multiple Credential Authentication. It just requires that a type of credential exist for each type of factor that the RP requires. The user can send proof of all the required "factors" to the RP at the same time, using multiple credentials.

For example, an RP can require the user type in a password, have a USB key, and scan their fingerprint. Proof of all of these "factors" can be sent to the RP using credentials. The USB key can contain a private key or implement a full Login Manager API. (i.e. send a private key signature to the RP.) A Login Manager (or browser) can use cryptography to create a private key out of the password. (i.e. send a private key signature to the RP.) A User Authenticator or browser can scan a fingerprint and send it to the RP.

User Authentication Detail

In order to login to an RP, a user must prove their identity to the RP. Typically, a user submits a "proof of identity" to the RP. This "proof" may be as simple as a username and password. An RP may store a Credential Verification Rule (CVR) in order to authenticate a user. This list of CVR. The RP typically requires that the "proof of identity" must satisfy some subset of the CVR criteria in order to be valid. (e.g. during an attempt to login to the RP.) An algorithm that uses the set of CVR to verify a "proof of identity" is called an "identity verifier".

The CVR can consist of a public key, a password, a certificate, an algorithm, a database record, a website response, etc. See the RP User Authentication Process. An RP usually stores different CVR for each user identity in an internal database record. The RP may allow a user to add, remove, or set the CVR for themselves. (For example, an RP can allow a user to change their password.) See the "cls/setActiveCredentials" serviceOp. For example, an RP may allow a user to turn on and off Multi-factor authentication.

A "Credential Verification Rule" is usually the opposite of a "credential". A "CVR" is a test for a required condition, while a "credential" is proof of a condition. (However, in the case of a "password", both could be the same value.)
Each CVR must have an associated "type" or "Credential Verification Method". This "type", or algorithm, defines how to verify if a "proof of identity" satisfies the CVR requirement. For example, If the CVR is a public key, then the "type" of the CVR denotes what format the key is in, and how to verify if a digital signature was created by the matching private key. An RP must know the "Credential Verification Method" for each type of CVR it supports. An RP can publish what types of Credential Verification Rule it supports in the supported.credentialReg property of the RP Service Descriptor.
There are two main types of Credential Verification Rule (CVR). There is "Site-specific" (i.e. Regular) and "multi-site". CVR are only applicable to a single RP. They are usually a type of "password" or "public key" and are usually stored in a database at the RP website. An RP is free to use any type of CVR it wants, and that browsers support. The "Multi-site UserId Credential Verification Rule" are applicable to all RPs. They are not "tied to" or limited to a single RP.

CLS Request: Set Credential Verification Rules Detail

The CLS Request, sent from the browser to the RP, can contain a list of Credential Verification Rules. (i.e. called the cvrList.) This list is how the user delivers to the RP the set of Credential Verification Rules that the RP should store for future user authentication.

The RP stores a set of "Credential Verification Rules" for each user. It uses these CVR to verify the credentials sent to it during login. (i.e. during the authentication process.) The user sets what CVR the RP stores by using the "setActiveCredentials" command. (i.e. It performs similar to a "change password" operation on systems that use a username and password.)

The list of CVR is located in the "CVR registration" section of the Service Request. (i.e. In the "uac" object.) This allows the user to set all the CVR in a single request.

Note that each Credential Verification Rule (both stored by the RP, and in the cvrList) can be of a different credential type. And new types of credentials can be created. The only requirement is that both the RP and the Login Manager support the new credential type. The mix of different types stored by the RP allows it to support Multiple Credential Authentication and Multi-factor authentication.

The CLS Request can also contain multiple "credential proofs". This is for user authentication, when a user wants to login. (i.e. It can be used to perform Multiple Credential Authentication.) This is how browsers can send multiple user credential proofs to an RP, all in the same request. The service request has two different sections for proofs, (1) the signatures section, for private key signatures, and (2) the credentialProofList section, for all other types of credential proof.

The "signatures" object can hold the signatures for multiple "public key" type credentials. The credentials can be digital signatures (i.e. public key cryptography) or they can be keys generated from passwords or federated credentials. Note that EACH signature in the "signatures" object has has digitally signed the entire payload of the Service Request. The CLS Request values, "reqOp" or "exp", etc. cannot be changed without generating a new signature. Because of this, signatures are preferred over other types of proof.

The "credentialProofList" section can hold the proof for any credential that is not a public key. It can contain multiple "credentialProofItem.value" objects of different types. Use the "credentialProofItem.format (cpf)" property to hold the type of proof.

Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "login", "sub": "cls/login", "iat": 1503971280, // issuedAt timestamp "exp": 1533064012, // expiresAt timestamp "aud": "RP_example.com", // the audience "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", // nonce value "nit": 1533064012, // nonceIssueTime "uid": { "raw": "ciq:C:F1:1:1234567890:ACMA_org", // The ciq UserId "ue1": "q3jC9-h" // Use "ue1" with "cls/login". }, "user_auth_method": "only_MSUID", "redirectUri": "/some/path/page.html", "useCount": 42,
// user_id_certificate_chain (Not available when using the "stored_cred" uauth_method.) "uic_chain": [ {"uic.format":"JWS", "uic.csvm":"YY", "ucv": { "payload":"82h7vb...", "signatures": [...] }} ],
// crProofSection. "crProofSection": { "uid": { "raw2": "ciq:C:B1:2:xxxxxxxx", // The ciq UserId }, "uapCounter": 42, "cpl": [ { "cpid": "cd2", "cpt": "pubkey", "cpf": "TBD-CPF", // "credentialProofItem.format": "TBD-CPF" (not necessary. The default is "TBD-CPF".) "cpv": "mmmm" // base64url encoded JWT or signature. } ] }, /* uac_registration. Not required for "login" reqOp. "uac": { "backup_credentials": [ { "cvid": "cd-3", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { ... } } ], "cvrList": [ { "cvid": "cd10", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { "kty": "EC", "kid": "cd10", // "kid" is REQUIRED. Is the same as the "cvid". "crv": "P-256", "ext":true, "key_ops": ["verify"], "x": "5sy3ogiqTrlC_FF7aOdCq7cNFsN2nbrH4xQmNCCBtso", "y": "ctK7P_LU-SQPf-ejkmC1JYzm7S5N0B6ZX5rwOQWzuv8" } } ] } */ }; let CLS Request = { "JWS": { "payload": BASE64URL(UTF8(payload_unencoded)), "signatures": [ { "protected": "eyJhbGciOiJFUzI1NiJ9", // protected_header = {"alg":"ES256", "sct":192} "header": { "kid": "cd1", "kid2": "e9bc097a-ce51-4036-9562-d2ade882db0d" }, "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga" }, { "protected": "eyJhbGciOiJFUzI1NiJ9", // protected_header = {"alg":"ES256", "sct":13} "header": { "kid": "userIdPK" // "userIdPK" means the public key is in "uid". }, "signature": "MG4mdj-hdfYHqJRnUxKa6e ..." }] } }
The "UserId certificate" JWT. (uid_cert_chain[0]) header and claims:
let payload_unencoded = { "sub2": "cls/certificate", "iss": "id_registrar.example.com", // The Backer "iat": 1503971280, "exp": 1533064012, "sub": "ciq:C:F1:1:1234567890:ACMA_org", // The ciq UserId. "uid": { "raw": "ciq:C:F1:1:1234567890:ACMA_org", // The ciq UserId. "usk": "q3jC9-h" }, "cert_pubKeyList": [ { "kty": "RSA", "kid": "f85762a7f52c8346", "alg": "RS256", "n" : "4b9e34...", "e" : "93bc32..." } ] } let jws_certificate = { "payload": BASE64URL(UTF8(payload_unencoded)), "signatures": [{ "protected": "eyJhbGciOiJSUzI1NiJ9", // protected_header = {"alg":"RS256", "sct":192} "header": { "alg": "RS256", "kid": "bf4a76332a6c8370f48", // "kid" is REQUIRED. ID of the issuer key. // "csvm": "OIDCD" // Get the sig verification key from the issuer via "OIDCD", etc. "csvm": "idr_keystore" // Get the sig verification key from an "Backer keystore". }, "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga" }] }

RP Configuration Options Detail

RP Configuration Options are name-value pairs the RP creates and gives to the browser in order to configure the browser's interactions with the RP. The options are usually embedded within HTML markup as a set of JSON-style properties in the "capis-config" attribute of one of the CAPIS HTML Elements. The options give the browser data or instructions about RP services without using javascript. This makes creating CAPIS enabled HTML easier, and CAPIS will work without requiring the browser to enable javascript for the RP.

There are two different types of RP Configuration Options in HTML. First, the Client Configuration Options are those configuration options in a CAPIS Link HTML element. (i.e. In the "capis-config" attribute.) They apply to the entire HTML page. Second, the Trigger Configuration Options are those configuration options in all RP Service Trigger HTML elements. They are only applicable to that single HTML element. (For Example, in a CAPIS Anchor "capis-config" attribute.)

In order for CAPIS to work, an HTML page MUST contain a CAPIS Link HTML element. And the CAPIS Link element MUST contain at least the "challenge" Client Configuration Option.

All the options in the "capis-config" attribute of a CAPIS HTML Element are written as JSON-style name-value pairs. (name:value, name:value) The entire set of options will be extracted by the browser into a single JSON object. That object will then be used as input to one of the CAPIS API functions. For Trigger Options, it will be used as a CapisAPI.callOptions value, and will be passed as input to the Capis Control.invokeServiceAction function.

An RP can put multiple RP Service Trigger HTML Elements on a single page, and use different configuration options in each one.

Not all configuration options are usable by all CAPIS HTML Elements. In particular, the "serviceOp" is only valid inside an RP Service Trigger and is not valid inside a CAPIS Link HTML element. Similarly, the "challenge" is only valid inside the CAPIS Link HTML Element not valid inside any RP Service Trigger HTML element.

All configuration options are case-sensitive. Both the property name and the value. Example: "serviceOp":"proveUserPresence", "serviceList", etc.

The names and values of the configuration options are defined by the "serviceSpec" that the RP uses. Different specifications can define different rp configuration option names. See "serviceSpec". Note that there are a few configuration options which are not defined in the serviceSpec. They are used before the RP Config Document is retrieved. These are capisDocUri, protocolHandlerList, serviceList and challenge.

HTML examples:
<link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required"}] '/> ... <a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a> ... <a href="/_capis/fallback/proveUserPresence.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/proveUserPresence", "redirectUri":"/some/path/page.html" '>Confirm my presence</a>
Javascript API examples.
capisLogin_api.performUserAuth("login", {redirectUri:"/some/path/page.html", challenge:"8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK"});
// TODO "challenge" is not in CapisAPI.callOptions.

Client Configuration Options

Client Configuration Options are the set of JSON-style properties in the capis-config attribute of a CAPIS Link HTML element. They are one of the two types of RP Configuration Options. They apply to the entire HTML page. The set of options is extracted into a single JSON object by the browser.

The ClientConfig Options provide a way for the RP to give the browser data or instructions about RP Services without using javascript. This makes creating CAPIS enabled HTML easier, and CAPIS will work without requiring the browser to enable javascript for the RP.

The ClientConfig Options MUST contain a "challenge" property. (A securely generated, long random number.) It must be different each time the page is refreshed.

Client Options can contain properties that are applicable to multiple services. (For Example, the challenge and serviceList.serviceItem properties can apply to multiple services.)

The other type of RP Configuration Options are Trigger Configuration Options. Trigger Options are contained in an RP Service Trigger HTML element. (Such as the CAPIS Anchor.) Trigger Options are only applicable to the single Trigger HTML element that contains them. Therefore, they usually contain only configuration options for a single service.

When an RP service is invoked, the CapisControl.invokeServiceAction API function will extract the Client Configuration Options for the HTML page. The browser will use the ClientConfig options for all RP Service calls. The browser will use the Trigger Configuration Options as the CapisAPI.callOptions argument.

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "capis_spec": "capis_base 0.1", "rpInfo": {"displayName":"ACME Corporation"}, "protocolHandlerList": [{"protocol":"cls", "serviceCas":["service_4"]}], "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required"}] '/>

Client Configuration - List of Properties

Client Config: Property "clientConfigData.clientSpec" (longName: "fubar")

Type string.

Specifies the spec version the options are written in.

Valid values are in the form of "capis_base 0.1". They must contain the word "capis_base".
{
  "capis_spec": "capis_base 0.1",
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "protocolHandlerList": [{"protocol":"cls", "serviceCas":["service_4"]}],
  ...
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}]
}
Example ClientConfig Options HTML:
<link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "capis_spec": "capis_base 0.1", "rpInfo": {"displayName":"ACME Corporation"}, "protocolHandlerList": [{"protocol":"cls", "serviceCas":["service_4"]}], "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required"}] '/>

Client Config: Property "clientConfigData.capisDocUri" (longName: "fubar")

Type string.

Specifies the URI of the RP RP Config Document. Overrides the defaultValues.capisDocUri of the RP Config Document. This option may ONLY be used in the CAPIS Link HTML Element.

Example ClientConfig HTML:
<link href="/some/path/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "capisDocUri": "https://RP_example.com/some/path/capis_config.json",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

Use of the "capisDocUri" property is ONLY supported on the CAPIS Link HTML Element. It is NOT supported on anchors and forms. (i.e. It is a Client Configuration Option.) If a "CAPIS HTML Element" anchor or form has a "capisDocUri" value, it will do nothing.

Rules

Allows an RP to put the RP Config Document somewhere other than the defaultValues.capisDocUri (i.e. in the "/.well-known" directory.) This is particularly useful if the RP does not have control over the "/.well-known" directory.

Allows different pages on the same website to use different RP Config Documents. Allows a single domain name to host multiple RPs. The login anchor for each RP can specify its own RP Config Document, at a different URI location.

Note that using a non-standard "capisDocUri" may require that the "audience" in the "proof of identity" be changed too. See the RP Config Document serviceDesc.baseSapId property.

Must start with either "/" or "https:", or it is invalid. If it is invalid, then the browser MUST throw an error.

If the location of the RP Config Document is not defined, (If the CAPIS Link HTML Element does not have either the "capisDocUri" property or the "href" attribute), then the defaultValues.capisDocUri is used.

If the CAPIS Link HTML Element has both an "href" attribute and a "capisDocUri" property, the "capisDocUri" property has priority.

When this property is present in an CAPIS Link HTML Element, it overrides the defaultValues.capisDocUri default behavior for all CAPIS HTML Elements on the page.

The only reason to set this property is to override the default. Perhaps to change the directory, or add a path component, or to remove the port number. (i.e. It doesn't make any sense to set the value to be the base domain name, as that is the default. Example: "https://RP_example.com")

A "capisDocUri" is a url using the https scheme. It identifies a JSON document at the RP. For convenience the address of the JSON document can be written starting with just a slash "/". If it is written like this, then "https" and the domain name (and port) of the RP website are automatically prepended to it.

The second type of URI, is simply a domain name using https. The URI can contain a sub-domain and a port, but it does not contain any path or a trailing slash. If the URI does not contain a path component, then the defaultValues.capisDocUri is automatically appended to the URI. (i.e. "/.well-known/capis_config.json")

Client Config: Property "clientConfigData.nonceIssueTime" (longName: "fubar")

Type string. Contains base64url encoded binary data. Required in the CAPIS Link HTML Element.

Contains a timestamp value created by the RP. Specifies the time the challenge was issued. This value is copied into the cls.request.nonceIssueTime value in the CLS Request. It may help the RP determine the user, the session, the freshness or staleness, etc.

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012, // timestamp
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

Client Config: Property "clientConfigData.challenge" (longName: "fubar")

Type string. Contains base64url encoded binary data. Required in the CAPIS Link HTML Element.

A "cryptographic nonce" value, created by the RP. base64url encoded. It is a securely generated nonsense value. (i.e. It is a long random number.) It is a binary value encoded using base64url. It is a type of "cryptographic nonce" value, used to perform user authentication. This option is REQUIRED in the CAPIS Link HTML Element.

A "nonce" value is simply passed back to the RP. It is a nonsense value used to distinguish a particular client session of an RP. Because it was created by the RP, and is passed back to the RP during authentication, it prevents certain CSS (Cross Site Scripting) attacks.

The "challenge" value, as with all "nonce" values, is to make sure that a cryptographic function is NEWLY performed, in response to a specific prompt. It prevents any previously generated cryptographic message from being used. The RP wants NEW proof that the user has a private key, so the RP generates a "nonce" value, and requires that the value be returned to it, inside the user login request. The User Authenticator creates a CLS Request message, includes the challenge in it, signs or encrypts the message with the private key, then sends the message to the RP. The presence of the challenge in the message proves that the signed or encrypted message was NEWLY generated. Therefore, the browser must currently have the private key.

A challenge value is REQUIRED in the CAPIS Link HTML Element.

The "challenge" value is a base64url encoded binary value (i.e. an integer). Therefore, it can only contain alpha-numeric, dash and underscore characters. (0-9, a-z, A-Z, '-', '_')

The RP can institute a time limit on between the page was sent and when the challenge must be answered.
Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

Client Config: Property "clientConfigData.protocolHandlerList" (longName: "fubar")

Type Array().

Specifies the list of protocol handler RP services. Each item contains 2 values. The protocol and the serviceCas.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "protocolHandlerList": [{"protocol":"cls", "serviceCas":["service_4"]}],
  ...
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}]
}
Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "protocolHandlerList": [{"protocol":"cls", "serviceCas":["service_4"]}],
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

Client Config: Property "clientConfigData.protocolHandlerList.protocol" (longName: "fubar")

Type string.

Specifies the protocol id to use for the "ua" service. Specifies a service in the RP Config Document.

{
  "documentId": "4857a8d28f6c",
  "protocolHandlerList": [{"protocol":"cls", "serviceCas":["service_4"]}],
  ...
}

Client Config: Property "clientConfigData.protocolHandlerList.serviceCas" (longName: "fubar")

Type Array.

Specifies the "cascading" list of services to use for the specified protocol. (serviceCs = service cascade list) The services will be tried in the order listed. Specifies the serviceId in the RP Config Document.

{
  "documentId": "4857a8d28f6c",
  "protocolHandlerList": [{"protocol":"cls", "serviceCas":["service_4"]}],
  ...
}

Client Config: Property "clientConfigData.protocolHandlerList.ras_endpoint" (longName: "fubar")

Type string.

Specifies the service id to use for the "ua" service. Specifies a service in the RP Config Document.

{
  "documentId": "4857a8d28f6c",
  "protocolHandlerList": [{"protocol":"cls", "serviceCas":["service_4"], "ras_endpoint":"endpoint_1"}],
  ...
}

Client Config: Property "clientConfigData.rpInfo" (longName: "fubar")

Type Object.
Information with which to identify credentials of the relying party. The properties in the "clientConfig.rpInfo" section override the RP Config Document properties with the same name. Also note that the CLS Service Descriptor serviceDesc.loginUseRules may contain an "id" property.
{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png",
    "siteName": "123done",
    "siteLogo": "/images/logo.png"
  },
  ...
}

Defines the information of the RP. Known items are "id", "displayName", "smallIcon".

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

The "displayName" specifies the display name of the RP.

The "smallIcon" specifies the URI for a custom logo to display to the user in the identity login box.

The "displayName" was previously known as "siteName". The "smallIcon" was previously known as "siteLogo".

Client Config: Property "clientConfigData.rpInfo.displayName" (longName: "fubar")

Type string. Default value: algorithm(The website domain name and port. -- The origin, without the protocol.)

Specifies the display name of the RP. The properties in the "clientConfig.rpInfo" section override the RP Config Document properties with the same name.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  ...
}
Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

Client Config: Property "clientConfigData.rpInfo.smallIcon" (longName: "fubar")

Type string.

Client Config: Property "clientConfigData.serviceList" (longName: "fubar")

Type Array(). Required.

An array of RP Service Descriptor objects. This option is typically used in the CAPIS Link HTML Element.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  ...
  "serviceList": [...]
}
Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required",
  "endpoint":{"sUri":"/_capis/cls/serviceCall.json", "http_method":"POST", "parameterList": [{"name":"capis_request"}],
  "request_format": "JWS"} }] '/>

Client Config: Property "clientConfigData.serviceList.serviceItem" (longName: "fubar")

Type Object.

Defines an RP Service Descriptor. This specifies the set of properties for an RP Service. At a minimum, it must include both a "protocol" and an "endpoint" or "endpoints" properties. A serviceItem can be defined in either the CAPIS Link HTML Element, or in the RP Config Document. For an example implementation, see CLS Service Descriptor and its List of properties.

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

Client Config: Property "serviceItem.id" (longName: "fubar")

Type Object.

Defines the identifier of the RP Service Descriptor. See serviceId.

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

Client Config: Property "serviceItem.protocol" (longName: "fubar")

Type Object.

Defines the protocol of the RP Service Descriptor.

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

RP Capis Document Detail

A "RP Capis Document" is a JSON document published by an RP that describes the RP and its public services using Capis format. The document includes a list of RP Service Descriptors, these identify the public RP Services the RP offers. A descriptor specifies the abilities and requirements of an RP Service. The list can include login or other authentication services.

The document must contain (1) a "documentId" value, (2) a "rpInfo" property, and (3) a "serviceList".

The defaultValues.capisDocUri of the "CAPIS Document" is a "well-known" URI. (Example: "RP_example.com/.well-known/capis_config.json".)

Each "service descriptor" contains (1) The "protocol" of the service (REQUIRED), (2) An "endpoints" array with at least one entry. Each endpoint must have an address URI (the "endpoint.sUri" is REQUIRED), (3) The other abilities and requirements of the service. (These are listed in "supported" and "required" sections.) (4) The "id" of the service.


(Note that comments, denoted by the // characters, are not allowed in JSON, and must be omitted.)
{
  "capis_spec": "capis_base 0.1",
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "protocolHandlerList": [{"protocol":"cls", "serviceCas":["service_4"]}],
  "serviceList": [ // Array of "RP Service Descriptor" objects.
    {serviceItemStart
      "id": "service_1", // Default id is "service_n".
      "protocol": "capis_login_service", // "protocol" is REQUIRED
      "serviceSpec": "capis_login_spec 0.1",
      "baseSapId": "example.com/some/manifest.json",
      "endpoints": [
        { "id": "endpoint_1", "http_method": "POST", // Default http_method is "POST"
        "sUri": "/_capis/cls/serviceCall.php", // REQUIRED. Define the endpoint URI.
        "request_format": "JWS" }
      ],
      "userIdRules": {
        "userIdTypes": ["single_site_userId", "ciq:C:B1:9:ri"],
        "createMethods": ["assigned_ulc", "claim_ms_ulc"]
      },
      "loginUseRules": {
        "altSapIdList": [ {"id":"login.example.com/manifest2.json", "colType":"SSO"},
          {"id":"example.com/manifest3.json", "colType":"SSO"} ]
      },
      "mediation": "silent",
      "userAuthenticationRequirements": {
        "allowedScope": {"rpMatch": [{"id":"example2.com", "all-subdomains":"yes"}]},
        "loginConfigurations": [
          { "id": "cfg1", "allow": "always", "credentialInfoList": [
            {"type":"module", "mid":"pubKeyFirst"} ]
          },
          { "id": "cfg2", "allow": "always", "credentialInfoList": [
            {"type":"module", "mid":"passwordCred2"} ]
          }
        ],
        "credentialInfoModules": [
          { "id": "passwordCred2", "allow": "always", "credentialInfoList": [
            { "type":"password", "transport":"raw" } ]
          },
          { "id": "pubKeyFirst": "allow": "always", "credentialInfoList": [
            { "type":"public-key", "COSE_alg": -7 },
            { "type":"public-key", "COSE_alg": -257 } ]
          }
        ]
      },
      "supported": {
        "userAuthScheme": {"methods":["stored_cred", "only_MSUID"]},
        "credentialReg": {
        // The types of "Credential Verification Rule" the RP supports.
          "ruleTypes": {"pubkey1":"1"},
          "passwordTypes": [{"name":"password_s1", "maxLength":14, "storageQuantity":"1"}],
          "publicKeyTypes": [{"name":"pubkey_s1", "JWA_alg":"ES256", "storageQuantity":"1"}],
          "required_ruleTypes": {"pubkey1":"1"}       // The RP requires a "public key" authentication.
        },
        "supported.uic.csvm": ["basic1", "basic2"] // The certificate verification protocols the RP supports.
      },
      "requirement_section": {
      }
    serviceItemEnd},
    {
      "id": "service_2", // "id" is REQUIRED
      ...
    }
  ]
}

List of CAPIS Document Properties

Client Config: Property "clientConfigData.documentId" (longName: "fubar")

Type string. Optional.

Specifies the id of the document. Each document revision should have its own unique id.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  ...
  "serviceList": [...]
}

Client Config: Property "clientConfigData.generate_challenge" (longName: "fubar")

Type string.
Specifies the URL of the generate challenge JSON file. Will generate a "cryptographic nonce" value. base64url encoded.

The RP Config Document may contain a "generate_challenge" property, to specify a way to generate a challenge.

json_doc = { ... "generate_challenge":"/_capis/cls/generate_challenge.json", ... }

{
  "documentId": "4857a8d28f6c",
  "generate_challenge": "/_capis/cls/generate_challenge.json",
  ...
  "serviceList": [...]
}

Trigger Configuration Options

Trigger Configuration Options are the set of JSON-style properties in the capis-config attribute of an RP Service Trigger HTML element. (For example, in the capis-config attribute of the CAPIS Anchor.) The set of options is extracted into a single JSON object by the browser. When the trigger is activated, this object is used as a CapisAPI.callOptions value, and is passed into the Capis Control.invokeServiceAction function.

The Trigger Options provide a way for the RP to give the browser data or instructions about RP Services without using javascript. This makes creating CAPIS enabled HTML easier, and CAPIS will work without requiring the browser to enable javascript for the RP.

The Trigger Options MUST contain a "serviceOp" property. The serviceOp property is part of the CAPIS Specification. All other properties are defined as part of a different specification, such as the CapisLogin Specification.

The Trigger Options are only used when the trigger is activated. They do not apply to the entire HTML page. The Trigger Options are one of the two types of RP Configuration Options. The other type is Client Configuration Options. Which is used in the capis-config attribute of a CAPIS Link HTML element. Those are applicable to the entire HTML page.

There are currently two instances of RP Service Trigger in HTML. These are the CAPIS Anchor and the CAPIS Form. (In the anchor capis-config attribute and in the form capis-config attribute, respectively.)

HTML examples:
<a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a> ... <a href="/_capis/fallback/proveUserPresence.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/proveUserPresence", "redirectUri":"/some/path/page.html" '>Confirm my presence</a> ... <form action="/_capis/fallback/signForm.html" handling="capis-trigger" capis-config=' "serviceOp":"cls/signData" '> <input type="text" name="first_name" placeholder="Enter your first name" /> <input type="text" name="user_email" placeholder="Enter your email address" /> <input type="submit" value="Sign and Submit the Form" /> </form>

CAPIS TriggerConfig: Property "triggerData.serviceOp" (longName: "fubar")

Type string. Usable by (and required in) a CAPIS Anchor and a CAPIS Form HTML Elements. (Not usable by a CAPIS Link.) Default value: "cls/login"

Specifies the operation to be performed by the RP Service Trigger. (i.e. When the anchor is clicked or the form is submitted.) This property is not for use in the CAPIS Link HTML Element. Usually the contained opId value is sent to the RP in the CLS Request.reqOp property, and the RP executes the requested operation.

The "serviceOp" property contains the "Service Protocol Id" before the slash, and the opId after the slash. (The Protocol ID corresponds to the "serviceDesc.protocol" in the RP Service Descriptor.) The protocol specifies which RP Service the serviceOp belongs to. This specification allows a single HTML page to use multiple services and/or multiple methods offered by the services. There must be a way to specify which service an RP Service Trigger wants to invoke.

The opId value must be one of the CLS Operation List. The following are possible values for the "serviceOp" property. "cls/login", "cls/logout", "cls/createUserLogin", "cls/setActiveCredentials", etc.

Example Anchor:
<a href="/_capis/fallback/setActiveCredentials.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/setActiveCredentials", "redirectUri":"/some/path/page.html" '>Set Active Credentials</a>

CLS Trigger Config - Detail

The CLS Specification extends the CAPIS specification, and defines its own properties. (The CLS Service Protocol Id)

CLS Trigger Config - List of Properties

CLS TriggerConfig: Property "triggerData.redirectUri" (longName: "fubar")

Type string. Usable by an anchor or form. (Not usable by a CAPIS Link.)

Specifies the URI of the page the browser should load after the success of the authentication operation. Alternate name is "return_to".

Tells the RP where to redirect the current browser tab, once the auth attempt has been successful. It can be another page on the RP website, or elsewhere on the internet. Note that this is a request. The RP does not have to comply with it. In particular, an authentication failure will result in an error page, it will not redirect the user to the redirectUri page.

Example Anchor:
<a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp": "cls/login", "redirectUri": "/some/path/page.html" '>Login</a> ... <a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp": "cls/login", "redirectUri": "https://example.com/some/path/page.html" '>Login</a>

CLS TriggerConfig: Property "triggerData.userIdRuleCfg" (longName: "fubar")

Type Object. Usable by an anchor or form. (Not usable by a CAPIS Link.)

Specifies the UserId and related configuration values to request the RP assign to the UserLogin. This value is primarily used with "requested_ulc UserLogin Creation Method". This value is primarily used with opId "createUserLogin", "changeUserId" and "login". This value is part of a REQUEST to the RP to assign the specified UserId to the UserLogin. The RP may or may not comply. This value is primarily used to send a Multi-site UserId to the RP.

The CLS Descriptor userIdRules value tells the browser what the RP's rules are. The CLS TriggerConfig userIdRuleCfg asks the RP to change its default behavior.

When used in the browser with "cls/login", the value is only used if the user chooses to create a new user login. If so, then the uid.clientReqUserId value is sent to the RP with action="createUserLogin". When used with "createUserLogin" and "login", the LoginManager.createUserLogin function is called, and the *original* userId is set to the desired value. However, the RP may decline to use the UserId, and respond with a different UserId value. This will change the userId value in the LoginManager. When used with "changeUserId", the value is not stored in the LoginManager at all all, unless and until the RP responds with confirmation that the value was assigned.

Example Anchor:
<a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp": "cls/login", "userIdRuleCfg": {"genMethods": ["st1", "ct1"], "rawUserId": "ciq:C:A:3:X0s5eA:Aq"}, "redirectUri": "/some/path/page.html" '>Login</a> ... <form ... handling="capis-trigger" capis-config=' "serviceOp":"cls/signData", "userIdRuleCfg": { "genMethods": ["st1","ct1"] }, "setUserIdRuleCfgByFieldId":"input27" '> <input type="text" name="user_email" value="john@example.com" placeholder="Enter your email address" /> <input id="input27" type="text" value='{ "genMethods": ["st1","ct1"] }' /> </form>

CLS TriggerConfig: Property "triggerData.setUserIdRuleCfgByFieldId" (longName: "fubar")

Type Object. Only usable by a form. (not an anchor)

Specifies the "id" of the form element (i.e. an input field) that contains the UserId configuration. This field is an alternate way to specify the "userIdRuleCfg" property.

This property is only used with forms. To set the UserId for an anchor, use the "userIdRuleCfg" property.

When the form is submitted, the browser will extract the value from the element, and will set the "userIdRuleCfg" property in the callOptions to be the result value. (See the "extractConfigOptionsFromElement" method.) This field is a way for the user (etc) to dynamically input the UserId configuration into a form, without requiring the HTML page to support javascript.

Can be used for either "User Login creation" or "user authentication" (such as "cls/login"). (If the browser wants to do something special with the UserId in the page, before it is sent in the request.)

Example use: (in ClientConfig)
<link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required"}] '/> ... <form ... action="/_capis/fallback/login.html" handling="capis-trigger" capis-config=' "serviceOp":"cls/login", "setUserIdRuleCfgByFieldId":"input27_userIdInfo" '> <input type="text" id="input27_userIdInfo" name="userIdCfg" placeholder="{ Enter the JSON. }" /> <input type="submit" value="Login" /> </form>

This property is used to specify a Single-site UserId. (As opposed to a Locked Id.) Therefore, it is only used when the RP supports the "single_site_userId" userIdRules.userIdTypes. (And the "stored_cred" supported.userAuthScheme.)

This configuration option is set by the RP to tell the browser which form field contains the "Single-site UserId". This way, the RP can provide help to the user when choosing a Single-site UserId, or validate the UserId, before the browser sends the "authentication request" to the RP.

This option can be used when doing a login via a form. This may be useful for some situations. It can be used to get the user's UserId into the HTML page before sending the request to the RP. This can be used to enforce some kind of restriction on the UserId, etc. Perhaps to force the user to select from a list of preferred identifier types, etc. (Or a restriction of the identifier namespace, etc.) This may require custom javascript on the RP web page.

<link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required"}] '/> ... <form action="/_capis/fallback/signUp.html" handling="capis-trigger" capis-config=' "serviceOp":"cls/createUserLogin", "setUserIdRuleCfgByFieldId":"input27_userIdInfo" '> Please enter a username and click the "check" button to see if it is already taken. <!-- Javascript should be attached to the "check" button, to dynamically query if the username exists. --> <input type="text" id="input27_userIdInfo" name="userIdCfg" placeholder="{ Enter JSON properties. }"/> <input type="button" value="Check if username is taken"/><br/> When you are finished selecting a username, press the "Create Account" button. Your browser will then prompt you to create and store a password. (Or a public key)<br/> <input type="submit" value="Create Account" /> </form>

CLS TriggerConfig: Property "triggerData.setServiceActionByFieldId" (longName: "fubar")

Type string. Only usable by a form.

Specifies the "name" of the input field that contains the serviceOp. This is typically only used for testing and debugging implementations.

Example Anchor:
<form href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp": "cls/login", "setServiceActionByFieldId": "serviceOp", "redirectUri": "/some/path/page.html" '> ... <input type="text" name="serviceOp" value="cls/login" /> <input type="submit" value="Submit" /> </form>

Specification Default Values

The "specification default values" are used when the corresponding value in the RP Configuration Options is not defined in an HTML page. The configuration options that have "specification defaults" are the capisDocUri and the protocolHandlerList.

  1. The default value of the href attribute of the CAPIS Link Element. (The value is the defaultValues.capisDocUri of the RP Config Document.)
  2. The default value of ClientConfig Options.protocolHandlerList.protocol is "cls".
  3. The default value of ClientConfig Options.protocolHandlerList.serviceCas is ["service_4"].
  4. The default value of ClientConfig.protocolHandlerList.serviceCas is ["service_4"].
  5. The default value of CLS Descriptor.id is "service_n". Where "n" is the element number in the serviceList array. (Starts with 1) (The id of the service.)
  6. The default value of CLS Descriptor.serviceSpec is "capis_login_spec 0.1",
  7. The default value of CLS Descriptor.protocol_id is "capis_login_service".
  8. The default value of CLS Request.request_spec is "capis 0.1".
  9. The default name of the HTTP parameter containing the CAPIS service request is "capis_request".
  10. The default directory name for "capis login authentication" files is "/_capis/cls".
          "endpoints": [
            { "id": "endpoint_1", "http_method": "POST", // Default http_method is "POST"
            "sUri": "/_capis/cls/serviceCall.php", // REQUIRED. Define the endpoint URI.
            "request_format": "JWS" }
          ],
    
  11. The default directory name for "fallback" files is "/_capis/fallback".
    Example Anchor:
    <a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config='"serviceOp":"..." '>Login</a>
  12. "capis_request" is the default name of the HTTP parameter containing the CAPIS service request.

Specification Default Values: capis_request

Type string. Required.

The default name of the HTTP parameter that contains the CAPIS service request. It is JSON data.

The browser sends the service request to the "RP service endpoint" in whatever manner the RP designated in the RP Service Descriptor. (i.e. In the RP Config Document.) Usually the method is an HTTP POST. In the case where the CAPIS HTML Element that activated CAPIS is a form, and CAPIS is configured to send an HTTP POST, then the browser sends the service request as a special HTTP parameter *in addition to* any regular form data. The default name of the HTTP parameter is capis_request. See endpoint.parameterList. See the CAPIS Service Invocation Flow.

The CLS Request JSON object contains a crProofSection" ("prs") property, and the "reqOp" to be performed.

Capis Login User Auth Method (uauth_method)

How a user is authenticated. How he signs-in to an RP. A user must prove that they are who they claim to be. Several ways to do this are:

  1. prove access to a shared secret (such as a password)
  2. prove possession of a private key (by creating a key signature)
  3. prove that the user is authorized by a different RP. (i.e. a federated credential)
  4. prove ownership of a Locked Id.
  5. Some combination of the above

Using any of the "certificate_" variations (such as "only_MSUID") means that a type of "UserId certificate" is being used. Be careful to use to correct "csvm" value.

In general, which "authentication method" the browser chooses to use, will also determine what "csvm" value needs to be sent to the RP. "CLS Request.sigInfo.csvm" is used for Certificate Signature Verification Protocol.

(The "csvm" values include "OIDCD", "BrowserID" and "RDAC".)

List of User Auth Methods (i.e. Login Methods)

List of user authentication methods. These can be supported by an RP in CLS Descriptor.supported.userAuthScheme. And used by the browser in CLS Request.user_auth_method.

CapisLogin UA Method: "stored_cred"

The RP should use the stored set of Credential Verification Rule (e.g. passwords, public keys, etc.) to authenticate the user. This option will not work if the RP does not have any stored credentials for the user_login. This is the simplest form of user authentication. This is the default.

The RP must store some Credential Verification Rule (e.g. passwords, public keys, etc.) for each user.

This is the only user_auth_method for Single-site UserId>. (Or can without_MSUID be used too?)

The RP may choose to not support this user_auth_method. It may choose to support only the only_MSUID user_auth_method.

If the RP supports this option, then it (probably) means that the RP supports creating a "Single-site UserId" during login. (i.e. assigned_ulc or similar.)

CapisLogin UA Method: "without_MSUID"

The RP should not verify that the user owns the Locked Id. The RP should authenticate the claimed UserId using only the set of CVR that it has stored for the user. This option will not work if the RP does not have any stored credentials for the user_login.

The RP should not verify the ownership of the UserId. If the UserId is a Federated UserId the RP should not require or use the UserId certificate. Even if a UserId Certificate if provided by the browser. If the UserId is a Self-contained type, then the RP will not extract the lock requirements from inside the UserId.

This is a shortcut for browsers and the RP. It eliminates a lot of the work that usually is not necessary. It allows the use of a Locked Id during user authentication, but skips the step of verifying its ownership. This is possible because if the Multi-site UserId is recognized by the RP, (If there exists a user that uses the UserId), then the ownership of the Multi-site UserId was verified previously, during the "user login creation". (The login_creation method was probably "MSUID UserLogin Creation Method".)

This option is very useful if the RP already stores a set of CVR for the user. As long as the user has credentials, and chose sufficiently secure credentials, then it is not really necessary to require the user to also prove that he owns the UserId during every login. (i.e. to unlock the UserId.)

When using this option, the CLS Request signatures that have certPK, should have their sigInfo.vkm value set to "site_stored_vks".

This method can only be used if the RP stores some kind of "Credential Verification Rule" (e.g. a public key, password, etc.) for the user. This method also requires the user to store a Credential Source for the RP in his Login Manager. (A password or private key, etc.)

See "without_MSUID" User Authentication Method Detail.

CapisLogin UA Method: "only_MSUID"

The RP should use only the Locked Id to authenticate the user. It should not use any of the credentials stored at the RP.

This option entirely relies on the proof that the user "owns" the UserId. If the UserId is a Federated UserId, then it requires a UserId certificate and entirely relies on the Identity Provider.

See only_MSUID-user-authentication-detail.

CapisLogin UA Method: "combo_MSUID"

The RP should use the active credentials stored at the RP AND the Locked Id proof of ownership. This process will prove that the user "owns" the UserId.

User Login Creation at an RP

How to create a new UserLogin at an RP. See opId "createUserLogin". (A.K.A. user registration.) Used by CLS Descriptor.serviceDesc.userIdRules.

Creates a new "user login" at a website. This registers the current user of the RP. It assigns him a UserId and some type of login secrets. (i.e. Some Credential Verification Rules. A public/private key or "username and password", etc.) Creating a "user login" will allow the RP website to be able to identify the same user in the future.

A "user login" is not the same thing as an "account". This is because RPs may allow Account Sharing. That is, for multiple users to share the same account. Each user would get their own "user login", they would get their own UserId and password or public key, etc. but they would share a single "service account". Because of this, creating a new user login DOES NOT have to also create a new "service account" at the RP. Some RPs may require an additional step to "create an account". Normally, both the "user login" and the "service account" are created together. However, some times a user may not want to create their own account, they may want to "be added to a friend's existing account" instead. For this reason, there is an only_register option to specifically inform the RP to only "register" the user, and not to create a service account. (An RP may split the account creation process into two steps, so this flag may not be needed.)

Users create a new UserLogin at an RP in order to... be able to login again later. (1) Have a way to identify themselves to the RP (i.e. with a UserId) and (2) be able to prove that they are who they claim to be. (i.e. authenticate themselves to the RP.)

The user's browser creates a "cls/createUserLogin" CLS Request, includes some public key(s) etc. and sends it to the RP. The RP then sends a CLS Response back to the browser, with acknowledgment of user registration, or an error. The default behavior is for the RP website to include in the response the new assignedUserId that it has assigned to the user. However, some RP may allow users to choose their own UserId.

If a Locked Id is specified when creating a User Login, there is an extra step. The RP MUST VERIFY that the user can unlock the Locked Id before the RP can use it to create a User Login. An RP MUST NOT register a Locked Id to any of its users, unless the user can unlock the ID. Because that would allow someone who does not own the Multi-site UserId to create a login using the UserId. (This is a security risk)

An RP SHOULD NOT automatically create a user_login for a UserId in response to a "cls/login" CLS Request. For example, if a user attempts to login with a Locked Id, and the RP verifies the user unlocked the UserId, but the RP does not have a record of a user_login for that UserId, the RP MUST NOT automatically create a user_login for the current user. Instead, the RP must CONFIRM that the user wants to create a new user_login. This will prevent User Login creation due to user error. It is easy for a user to make a mistake, and accidentally select the wrong UserLogin to log in to an RP with. The user may already have an account at the RP, but with a different UserId. Or the user may want to change his existing account. For example, the user may want to change the account in order to allow the new UserId to access it. Because the RP does not know the user's intentions, automatically creating a new user_login would be a problem.

The RP may allow users to CHOOSE THEIR OWN UserId. The RP may provide the user with a list of suggested Single-site UserId. Or it may do something more creative and perform a dynamic lookup of what suggestion the user types in. Regardless, when the user activates the "cls/createUserLogin" serviceOp, the CLS TriggerConfig.userIdRuleCfg will contain the chosen UserId.

The CLS Request JSON object:

let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "createUserLogin", "sub": "cls/createUserLogin", "iat": 1503971280, // issuedAt timestamp "exp": 1533064012, // expiresAt timestamp "aud": "RP_example.com", // the audience "challenge": "abcdefg", // nonce value "nit": 1533064012, // nonceIssueTime "uid": { "raw": "ciq:C:B1:2:K8h3_TfXr6ZtLq7d1m8k", // The ciq UserId "timestamp_uid": "q3jC9-h" }, // "user_auth_method": "combo_MSUID", "user_login_creation_method": "claim_ms_ulc", "redirectUri": "/some/path/page.html",
// user_id_certificate_chain (Available when not using the "stored_cred" uauth_method.) "uic_chain": [ {"uic.format":"JWS", "uic.csvm":"YY", "ucv": { "payload":"82h7vb...", "signatures": [...] }} ],
"useCount": 42, // crProofSection. "crProofSection": { "uid": { "raw2": "ciq:C:B1:2:xxxxxxxx", // The ciq UserId }, "uapCounter": 42, "cpl": [ { "cpid": "cd2", "cpt": "pubkey", "cpf": "JWT", // "credentialProofItem.format": "JWT" (not necessary. The default is "JWT".) "cpv": "mmmm" // This is the encoded JWT, see below. } ], }, // uac_registration. Required for "createUserLogin" and "setActiveCredentials" reqOp. "uac": { "backup_credentials": [ { "cvid": "cd-3", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "bupk": "ciq:C:B1:2:mK7HnbndYb746GvnYkrU", // The Backup User Public Key ("backup_upk") "bupk2": "none" } ], "cvrList": [ { "cvid": "cd10", "typ": "pubkey", "COSE_alg": -7, "fmt": "JWK", "val": { "kty": "EC", "kid": "cd10", // "kid" is REQUIRED. Is the same as the "cvid". "alg": "ES256", "crv": "P-256", "ext":true, "key_ops": ["verify"], "x": "5sy3ogiqTrlC_FF7aOdCq7cNFsN2nbrH4xQmNCCBtso", "y": "ctK7P_LU-SQPf-ejkmC1JYzm7S5N0B6ZX5rwOQWzuv8" } } ] } }; let CLS Request = { "JWS": { "payload": BASE64URL(UTF8(payload_unencoded)), "signatures": [{ "protected": "eyJhbGciOiJFUzI1NiJ9", // protected_header = {"alg":"ES256"} "header": { "kid": "e9bc097a-ce51-4036-9562-d2ade882db0d", // "kid": "userIdPK" // "userIdPK" means the public key is in "userId". "vkm": "certificateF" }, "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga" }] } }
The "UserId certificate" JWT. header and claims: (uic_chain[0])
let payload_unencoded = { "sub2": "cls/certificate", "iss": "id_registrar.example.com", // The Backer "iat": 1503971280, // REQUIRED "exp": 1503971430, // REQUIRED "sub": "ciq:C:F1:1:1234567890:ACMA_org", // The ciq UserId. "uid": { "raw": "ciq:C:B1:2:K8h3_TfXr6ZtLq7d1m8k", // The ciq UserId }, "cert_pubKeyList": [ { "pkf": "JWK", "kty": "RSA", "kid": "f85762a7f52c8346", "alg": "RS256", "n" : "4b9e34...", "e" : "93bc32..." } ] } let jws_certificate = { "payload": BASE64URL(UTF8(payload_unencoded)), "signatures": [{ "protected": "eyJhbGciOiJSUzI1NiJ9", // protected_header = {"alg":"RS256", "sct":192} "header": { "alg": "RS256", "kid": "bf4a76332a6c8370f48", // "kid" is REQUIRED. ID of the issuer key. // "csvm": "OIDCD" // Get the sig verification key from the issuer via "OIDCD", etc. "csvm": "idr_keystore" // Get the sig verification key from an "identity registrar keystore". }, "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga" }] }

Account Creation at an RP

Users can create a UserLogin at an RP by using the opId "createUserLogin" value. RPs publish their requirements for User Login creation in the serviceDesc.userIdRules property.

When creating a UserLogin at an RP, a user must do a few things. In order to be able to login again later. (1) Have a way to identify themselves to the RP (i.e. with a UserId) and (2) be able to prove that they are who they claim to be. (i.e. authenticate themselves to the RP.)

Ways to create a UserId.
  1. The RP assigns a UserId.
  2. The RP provides a list of options. (The user chooses from several options.)
  3. The RP makes suggestions. (i.e. interactivity between the user and the RP.)
  4. The user requests a UserId. The RP may approve the request.
    Usually, the RP publishes some list of requirements for the identifier. For example: The UserId must be "unused". There is a limited character set to choose from. There is a maximum length, etc. Limited interactivity (negotiation) with the RP is necessary, to find out if a desired UserId is already in use.
  5. Use a "Locked Id".
    It is a universally unique UserId, that is guaranteed to be "unused". (Because the UserId is RESERVED. The RP must not register it to a user, unless the user can unlock the ID. i.e. Prove he owns it.) Note: Multi-site UserIds may use some characters that are not available to "Single-site UserIds". Or may start with a unique prefix. (i.e. "ciq:C:B1:", "ciq:C:F1:") See CIQ UserId format.

Options 1, 2 and 3 are "Single-site UserIds". Because they only have meaning at that single RP.

There are two choices for how to set the Credential Verification Rule. (i.e. CVRs)
  1. Send the CVRs to the RP upon User Login creation. (i.e. password and/or public key, etc.) The RP will store the CVR associated with the UserId. It uses the CVR to authenticate the user on subsequent logins.
  2. Do not send any CVR to the RP on User Login creation. Or, the RP does not store any CVR. For a time, the RP relies exclusively on external forces to authenticate the user. This requires a Locked Id. (It requires more than a "Single-site UserId", because there is no password.) The RP can rely exclusively on the user's MSUID (on the CVR in the MSUID), a federated MSUID. etc.
The RP can also allow users to update the Credential Verification Rule that it stores for them. So both of the above cases are not permanent, and can be modified over time.

There must be some way of telling if an account already exists for the supplied username or MSUID. One way to do this is that the RP can require a "register-MSUID" package (i.e. a User Login creation) (the package contains a public key and username) sent with a form submission. (The form submission can include user name, email address, etc.)

When creating an account, the RP might allow additional Credential Verification Rule (i.e. public keys) to be set. (2nd factor authentication) The public keys can be sent to the RP in an additional CLS Request.property. The keys can be in JWK format. When logging into an RP, the second signature can be sent to the RP in this second property. See "req_factor2".

See UserLogin Creation Methods for a list of the possible values.

List of UserLogin Creation Methods

The UserLogin Creation Methods. Used in the serviceDesc.userIdRules.createMethods. Used in the cls.request.user_login_creation_method value. Used with the "createUserLogin" opId.

Previous values are SSUID_acm and MSUID_acm.

Login Creation Method: "assigned_ulc"

The RP assigns a new Single-site UserId without any user intervention. The "assigned_ulc" value is the default. See cls.request.user_login_creation_method See serviceDesc.userIdRules.createMethods.

When the RP is sent a "createUserLogin" opId. The RP sends back a new assignedUserId in the CLS Response.

Login Creation Method: "claim_ms_ulc" Claim a Multi-site UserId

The user claims a Locked Id as his UserId.

The RP may limit the types of Locked Id that it supports. See the user identifier type supported by the RP.

A simple way for a user to create a UserLogin at an RP. The user provides a Locked Id and proof of ownership of the UserId. This skips the hardest part of traditional User Login creation, having the user find (and remember) an unused Single-site UserId.

See MSUID_acm.

Login Creation Method: "requested_ulc"

The user requests a specific UserId from the RP.

Used with CLS TriggerConfig.userIdRuleCfg and CLS Descriptor.userIdRules.

Login Creation Method: "requested2_ulc"

The RP negotiates a UserId with the user.

The user performs some interactive process with the RP to negotiate a new Single-site UserId. This is only used when the user has NOT provided a Locked Id. And there is no UserId certificate.

In this case, there is no UserId Certificate. There is only the UserId Assertion, and the RP has the sig verification key for it. The RP stores some "Credential Verification Rule" (e.g. a public key) for each user. (The UserId Assertion should use a "sigInfo.vkm" value of "site_stored_vks".)

See SSUID_acm.
31 32 33 34 35 36 37 38

CLS Service Descriptor Detail

A CLS Service Descriptor is a specific version of an RP Service Descriptor. It is used for User Authentication.

A CLS Service Descriptor specifies the capabilities and requirements of an RP's "User Authentication service". It is one type of "RP Service" and uses a custom "RP Service Descriptor". (Currently the specification is "capis_login_spec 0.1")

{
    "id": "service_1",
    "protocol": "capis_login_service",
    "serviceSpec": "capis_login_spec 0.1",
    "baseSapId": "example.com/some/manifest.json",
    "endpoints": [
      { "id": "endpoint_1", "http_method": "POST",
      "sUri": "/_capis/cls/serviceCall",
      "request_format": "JWS" }
    ],
    "userIdRules": {
      "userIdTypes": ["single_site_userId", "ciq:C:B1:9:ri"],
      "createMethods": ["assigned_ulc", "claim_ms_ulc"]
    },
    "loginUseRules": {
      "altSapIdList": [ {"id":"login.example.com/manifest2.json", "colType":"SSO"},
        {"id":"example.com/manifest3.json", "colType":"SSO"} ]
    },
    "mediation": "silent",
  /* One possible suggestion. Old style.
        "acceptableCredentials": {
          "password": {minEntropy: 64},
          "federated": {providers: ["https://accounts.google.com", "https://www.facebook.com", ...]},
          "sms": {  checkBy: {      send: function(number) {/*Ask the server to send an SMS*/},
            "vouch": [googleKey, samsungKey, appleKey, ...],        },      },
          "publicKey": { // <-- Better name for webauthn credentials.
            "attestationChallenge": crypto.getRandomValues(sixteen_byte_buffer),
            "cryptoParameters": [{algorithm: "ES256"}],
            // Do we need a filter for acceptable attestation certificates?
          }
        },
  */
    "userAuthenticationRequirements": {
      "comment_21": "Each loginConfiguration details the number and type of credentials required for that configuration.",
      "allowedScope": {"rpMatch": [{"id":"example2.com", "all-subdomains":"yes"}]},
      "loginConfigurations": [
        { "id": "cfg1", "allow": "always", "credentialInfoList": [
          {"type":"module", "mid":"pubKeyFirst"} ]
        },
        { "id": "cfg2", "allow": "always", "credentialInfoList": [
          {"type":"module", "mid":"passwordCred2"} ]
        }
      ],
      "credentialInfoModules": [
        { "id": "passwordCred2", "allow": "always", "credentialInfoList": [
          { "type":"password", "transport":"raw" } ]
        },
        { "id": "pubKeyFirst": "allow": "always", "credentialInfoList": [
          { "type":"public-key", "COSE_alg": -7 },
          { "type":"public-key", "COSE_alg": -257 } ]
        }
      ]
    },
        // Lists what Webauthn credential creation options the RP supports.
        "credentialCreationOptions": {
          "publicKeyCredentialCreationOptions": {
            // "Note that both the 'rp' and 'user' properties of Webauthn have been moved.",
            // "The 'rp' was MOVED up a level. The 'user' values MOVED to 'cls.serviceDesc.user_info'.",
            // "pubKeyCredParams is an array of type PublicKeyCredentialParameters. The order is important.",
            // "This Relying Party will accept either an ES256 or RS256 credential, but prefers an ES256 credential.",
            // "COSE_alg is a COSEAlgorithmIdentifier",
            // "-7 is the value for ES256. As registered in the IANA COSE Algorithms registry",
            // "-257 is the value for RS256. As registered by the WebAuthn specification",
          
            "pubKeyCredParams": [
              { "type":"public-key", "COSE_alg": -7 },
              { "type":"public-key", "COSE_alg": -257 }
            ],
          
            "timeout": 60000,
            "excludeCredentials": [],
            "extensions": {"loc": true},
            "attestation": "none",
            "authenticatorSelection": {
              "authenticatorAttachment": "platform",
              "residentKey": "required",
              "requireResidentKey": false,
              "userVerification": "preferred"
            }
          }
        },
        // Lists what Webauthn credential request options the RP supports.
        "credentialAssertionOptions": {
          publicKeyCredentialRequestOptions": {
            // "allowCredentials is an array of type PublicKeyCredentialDescriptor.",
            // "The id fields in allowCredentials, will be automatically converted into a Uint8Array.",
            // "id conversion is: Uint8Array.from(window.atob(id), c=>c.charCodeAt(0))",
            "timeout": 60000, 
            "allowCredentials": [
              { "type":"public-key" },
              { "type":"public-key", "id":"!!!!!!!hi there!!!!!!!\n" },
              { "type":"public-key", "id":"roses are red, violets are blue\n" },
              { "type":"public-key", "transports": [] }
            ],
            "userVerification": "preferred",
            "extensions": {
              "txAuthSimple": "Wave your hands in the air like you just don't care",
              "webauthnExample_foobar": 42
            }
          }
        },
    "supported": {
      "userAuthScheme": {"methods":["stored_cred", "only_MSUID"]},
      "credentialReg": {
          "ruleTypes": {"pubkey1":"1"},
        "passwordTypes": [{"name":"password_s1", "maxLength":14, "storageQuantity":"1"}],
        "publicKeyTypes": [{"name":"pubkey_s1", "JWA_alg":"ES256", "storageQuantity":"1"}],
        "required_ruleTypes": {"pubkey1":"1"}
      },
      "supported.uic.csvm": ["basic1", "basic2"]
    },
    "requirement_section": {
    }
}

Each authentication service descriptor MUST have a "cls.serviceDesc.protocol" and an "endpoint.sUri".

This protocol does not provide an attestation mechanism which allows RPs to identify the class of device and either accept it or not depending on the particular site's policy. Instead of telling the RP about the device, the RP publishes the class of device it accepts. "supported_device_type".

Note that all "supported" properties are arrays. (Example: "supported.credentialReg.ruleTypes": ["pubkey"])

CLS Service Descriptor - List of Properties

CLS Descriptor: Property "serviceDesc.id"

Type string. Not Required.

Specifies the id of the service. The default value is "service_n". Where "n" is the element number in the serviceList array. (Starts with 1) (Or in the serviceList array.)

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      "endpoints": [
        { "id":"endpoint_1", "http_method":"POST", "sUri":"/_capis/cls/serviceCall" },
        { "id":"grif", "http_method":"GET", "sUri":"/_capis/cls/verify.json" }
      ]
    serviceItemEnd}
  ]
}

Valid values are anything unique. Example: "service_1", etc...

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"id":"service_4", "protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

CLS Descriptor: Property "serviceDesc.protocol"

Type string. Default value: "capis_login_service"

Specifies the protocol handled by the service.

Valid values are "cls", "webauthn", etc..

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>

CLS Descriptor: Property "serviceDesc.default_endpoint"

Type string. Default value: "endpoint_n"

Specifies the default_endpoint of the service.

CLS Descriptor: Property "serviceDesc.serviceSpec"

Type string. Default value: "capis_login_spec 0.1" Not Required.

Specifies the name and version of the specification used by the service.

Different services offered by the RP can use different protocols and specifications.

Valid values are in the form of "capis_login_spec 0.1".

Specifies the name and version of the "serviceSpec" specification the RP requires. (Used for the Client Configuration Options in the HTML page.)

All the property names and values the RP uses in the configuration options in the HTML page are defined by the "serviceSpec" that the RP uses. With a few exceptions. There are a few configuration options which are independent of the serviceSpec, as they are used before the RP Config Document is retrieved. They are the capisDocUri and the protocolHandlerList properties.

Valid values: "capis_login_spec 0.1".
{
  "id": "service_1",
  "protocol": "capis_login_service",
  "serviceSpec": "capis_login_spec 0.1",
  "endpoint": {
    "id": "endpoint_1", "http_method": "POST", "sUri": "/_capis/cls/serviceCall"
  }
}

CLS Descriptor: Property "serviceDesc.ua_request_spec"

Type string. Default value: "uars 0.1"

Specifies the name and version of the UA specification the RP requires.

CLS Descriptor: Property "serviceDesc.endpoint"

Type Object. At least one endpoint is required.

An "endpoint" object contains settings for the RP endpoint. An endpoint can be either a single item, or one of the items in the "endpoints" array. (There cannot be both an "endpoint" and an "endpoints" property.)

Defines an authentication service endpoint.

An endpoint has the following properties:

{
  "id": "service_1",
  "protocol": "capis_login_service",
  "endpoint": {
    "id": "endpoint_1", "http_method": "POST", "sUri": "/_capis/cls/serviceCall"
  }
}

CLS Descriptor: Property "serviceDesc.endpoints"

Type Array(Endpoint). Required. At least one endpoint is required.

Defines the array of service endpoints.

{
  "id": "service_1",
  "protocol": "capis_login_service",
  "endpoints": [
    { "id": "endpoint_1", "http_method": "POST", "sUri": "/_capis/cls/serviceCall",
      "parameterList": [{"name":"capis_request"}],
      "request_format": "JWS"
    },
    { "id": "endpoint_2", "http_method": "GET",
      "sUri": "/_capis/cls/serviceCall.json",
      "request_format": "JWS",
      "parameterList": [{"name":"capis_request", "type":"object"}]
    }
  ]
}

CLS Descriptor: Property "serviceDesc.endpoint.id"

Type string. Default value: "endpoint_n" (Where "n" is an integer.) Not Required.

Specifies the id of the endpoint. The default is "endpoint_n". Where "n" is the element number in the array. (Starts with 1)

CLS Descriptor: Property "serviceDesc.endpoint.http_method"

Type string. Default value: "POST"

Defines the type of HTTP request to send to the endpoint URI.

Valid "method" values are "POST" and "GET".

CLS Descriptor: Property "serviceDesc.endpoint.sUri"

Type string. Required.

Specifies the URI of the authentication service endpoint.

Must start with either "/" or "https:". The https protocol is always used. If it starts with "/", then "https:" is prepended.

CLS Descriptor: Property "serviceDesc.endpoint.parameterList"

Type Array(). Not Required.

Specifies the list of parameters in the data sent to the RP.

The same parameter names are used with both HTTP GET and POST methods.

Lists the parameters that the endpoint takes, in order it takes them (if order is necessary). All parameters are optional by default, unless otherwise noted. Certain APIs may require a particular number of parameters, in a certain order.

{
  "id": "service_1",
  "protocol": "capis_login_service",
  "endpoints": [
    { "id": "endpoint_1", "http_method": "POST",
      "sUri": "/_capis/cls/serviceCall",
      "request_format": "JWS"
    },
    { "id": "endpoint_2", "http_method": "GET",
      "sUri": "/_capis/cls/serviceCall.json",
      "request_format": "JWS",
      "parameterList": [{"name":"capis_request", "type":"object"}]
    }
  ],
    ...
}

A parameter may also have a type. The default type is a JSON object. The type value can be "string", "integer", "boolean", "object", or "array".

CLS Descriptor: Property "serviceDesc.request_format"

Type string. Default value: "JWS"

Specifies the format of the request sent to the RP.

The default value of "JWS" is usually correct.

CLS Descriptor: Property "serviceDesc.ras_endpoint"

Type string.

Specifies the id of the endpoint to use. The endpoint must exist in the serviceList in the RP Config Document.

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required", "ras_endpoint": "endpoint_2"}] '/>

CLS Descriptor: Property "serviceDesc.user_info"

Type Object.

Specifies information about the user, to the user's browser, after User Login creation.

<link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required", "user_info": {"username":"ciq:C:A:3:X0s5eA:Aq"} }] '/> ... <form ... handling="capis-trigger" capis-config=' "serviceOp":"cls/signData" '> <input type="text" name="user_email" value="john@example.com" placeholder="Enter your email address" /> </form>

This property is used to inform the user's browser of the information the RP has, that might be of help to the user. For instance, that the user supplied to the RP. The browser can add this information to its internal data stores to augment the credentials, to help the user in the future.

Example: Inside the "user_info": {} data object:
user_info: {
  "id": "MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII=",
  "name": "alex.p.mueller@example.com",
  "displayName": "Alex P. Müller",
  "small_icon": "https://pics.example.com/00/p/aBjjjpqPb.png"
}

CLS Descriptor: Property "serviceDesc.baseSapId"

Type string. Default value: (the RP domain name)

Specifies the Service Application Identifier (sapId) to use for the RP. (i.e. The UserAuth ServiceApp) A sapId is the id under which a CAPIS service (such as Capis Login) stores data for a specific RP or organization. CapisLogin and the Login Manager) stores the User Logins for an RP, or organization under the sapId. A sapId is similar to a URI, however it does not have a scheme. (A scheme of "https" is assumed.) It may also contain additional parts, such as a GUID. Example: "login.example.com".

Usually, each RP creates its own sapId, and only allows itself to access User Logins that use it. However, a larger organization may set up multiple RPs to use the same sapId. (Known as SSO. Single Sign On.) Access to a sapId is validated, so that only an "authorized" RP can access User Logins that use that sapId.

The sapId is based on an RP's "domain name". It does not include a scheme or port number. It may include a path component, etc.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      "baseSapId": "example.com/some/manifest.json",
      "loginUseRules": {
        "altSapIdList": [ {"id":"login.example.com/manifest2.json", "colType":"SSO"},
          {"id":"example.com/manifest3.json", "colType":"SSO"} ]
      },
      "userAuthenticationRequirements": {
        "allowedScope": {"rpMatch": [{"id":"example2.com", "all-subdomains":"yes"}]}
      },
      ...
    serviceItemEnd}
  ]
}
Examples of sapId values:
  • "example.com"
  • "login.example.com"
  • "login.example.com/user/asmith"

A sapId identifies a subset of User Logins. The set can be authorized for use by a list of RPs. Multiple sapIds may exist for the same RPs. The RP gets to decide which sapId to use. (As long as it is authorized.)

The default value

The default behavior is to create the sapId based on the domain name of the current page. Without the scheme, port, or path. Example: If the current page is "http://login.example.com/some/place/like/home.html" Then the default value of sapId is "login.example.com".

A sapId is used to address a "proof of identity"

A "proof of identity" MUST be addressed to a sapId, or it is not valid. The contained "audience" field must contain the rpId of the RP. If an RP receives a proof of identity with an "aud" value that does not match itselfthen the proof is invalid, and the RP MUST NOT accept it. (i.e. an RP may only use a proof that is addressed correctly.) Same with the "forSapId" field. It must contain a known sapId. This is another way that prevents a "proof of identity" from being reused. (The other is the challenge.) A generated proof cannot be used to login to any RP other than the one for which it was created. Note that using a non-standard "capisDocUri" may require that the "audience" in the "proof of identity" be changed too. See the RP Config Document serviceDesc.baseSapId property.

What does a sapId do?

The sapId is used as a "scope modifier" for UserLogins. When logging in at an RP, the RP provides the sapId. This essentially "asks" the browser to use one of the UserLogins that use that sapId. The browser checks that the RP is authorized to use the sapId. (The browser will match the origin of the current page with those authorized by the sapId.)

For comparison, this is a slightly relaxed version of the way that cookies behave. Cookies are scoped to the origin. The sapId (1) ignores both the scheme and port, (2) is only dependent on the domain name, and (3) the browser can recognize that certain RPs are part of the same organization and can have those RPs use a shared sapId.

Specifically, a sapId is used in two ways. (1) When creating UserLogins. (2) When using UserLogins (i.e. to login). When creating a user login, the browser "attaches" the requested sapId to the user login. (The user login is indexed by the sapId in the Login Manager.) When attempting to use a sapId at an RP website, (to login, setActiveCredentials, etc.), only those UserLogins that MATCH the sapId will be made visible to the user.

The RP gets to choose what sapId to use during both scenarios. During user login creation and use. It can choose either a sapId that matches the RP domain name, or one that is a parent domain of it.

For example, if a user login was created using the sapId "login.example.com", and then the user tried to login at "example.com", the user login for "login.example.com" would NOT be visible. However, if the website at "login.example.com" forced the use of the sapId "example.com" (not "login.example.com"), for "create" (so that it was used for both "create" and "use" scenarios), then the user would be able to use the same user login at both URLs.

This has both good points and bad points. A good point is that a domain (i.e. "example.com") cannot read the UserLogins for any sub-domain. Another good point is that a sub-domain can force the *creation* of a user login using a parent domain. A bad point is that a sub-domain can *read* (i.e. access) all the UserLogins for all parent domains. Another bad point, if the website initially used a sub-domain, and then wants to change to use a parent domain, that is impossible.

Webauthn --- Note: rpId represents the caller’s RP ID. The RP ID defaults to being the caller’s origin's effective domain unless the caller has explicitly set options.rpId when calling get().

sapId are RESTRICTED

An RP cannot set the "registration" sapId value to whatever it wants. The sapId value must be a derivative of the web site's origin. All the RP can do is make it less specific. For example, if a web site is served on "help.login.example.com", the RP can set its sapId to be "login.example.com" or "example.com". This makes the sapId LESS specific than the default. This will cause, during credential creation, new credentials be tied to the LESS specific domain. That means that those credentials can be accessed by other sub-domains, like "site3.example.com".

During Credential Creation. ... default MAY be overridden by the caller, as long as the caller-specified RP ID value is a registrable domain suffix of, or is equal to, the caller’s origin's effective domain.

During Authentication. If options.rpId is not present, then set rpId to effectiveDomain. Otherwise: If options.rpId is not a registrable domain suffix of and is not equal to effectiveDomain, return a DOMException whose name is "SecurityError", and terminate this algorithm. Set rpId to options.rpId. Note: rpId represents the caller’s RP ID. The RP ID defaults to being the caller’s origin's effective domain unless the caller has explicitly set options.rpId when calling get().

CLS Descriptor: Property "serviceDesc.FIDO_appId" (longName: "fubar")

Type string.

No longer in use. This refers to an old specification used by FIDO.

Specifies one or more facets of the same application. A facet is either a domain name, sub-domain name, or an Android or iOS app key.

This specification defines a "Key Storage" system. This storage system is not part of a web browser, but is remotely accessible from a web browser, and from other applications. The system can be running on a device such as a phone and the applications may be phone applications. (Android or iOS applications.) The "Key Storage" system may be a physical device, (such as a USB stick) or it may be remote (i.e. running on an internet server). The "Key Storage" system assigns a "KeyHandle" to every key that it generates. A web browser, or other application, accesses the keys in the "Key Storage" by providing a keyHandle, and an AppID.

The "Key Storage" stores keys based on the RP. However, if that was the case, then all applications that wanted to access

If applications accessed keys with only a keyHandle, then there could be a malicious app, installed on the device (on the phone or desktop computer) that can bypass the security. It can try every possible keyHandle, in order to steal every key. Because of this, having only a keyHandle is too little security. Instead, an application must PROVE that it is allowed to access the "Key Storage" system for the desired keyHandle. If applications accessed keys by providing both a keyHandle and an RP identification string.

An appId value allows each of the specified facets to use the same authentication. A user can use a web browser, or an app on their mobile phone, and use the same credential to authenticate themselves to the application. The same username and public key, etc. Without an appId, each different application would have to have its own method of authentication. (A different username and password for each web browser, and for each mobile phone app.)

Most of the time, an appId is not needed.

The default is for the appId to be missing from the "RP Config Document" entirely. In this case, the browser uses a "default value" for the appId. This consists of the

Examples:
  • "https://RP_example.com"
  • "/app-id.json"
  • "https://example.com/app-id.json"

The specification must not allow one RP to access the credentials of another RP. What set of Web origins and native applications (facets) make up a single logical application and how can they be reliably identified? How can we avoid making the user register a new key for each web browser or application on their device that accesses services controlled by the same target entity? How can access to registered keys be shared without violating the security guarantees around application isolation and protection from malicious code that users expect on their devices? How can a user roam credentials between multiple devices, each with a user-friendly Trusted Computing Base for FIDO?

Default is the page origin. Example: "https://RP_example.com:2030"

The appId, if it exists, must be a JSON object that lists the facets of the application.

The appId document must be retrieved using an anonymous fetch. That is, the HTTP GET used to retrieve the document MUST not have any cookies, authentication, Origin or Referrer headers, and must not use any TLS certificates or other credentials. The response delivering the document MUST have a MIME Content-Type of "application/json".

The appId only needs to be specified if the application can be reached through multiple urls and/or mobile. If connecting to the app on a different url, but it has the same app-id, it instructs the browser (or app) to use the same proof (use the same private key on both urls). Without the app-id, accessing the service via different means would use different private keys. See App ID and FIDO Alliance Specification .

{
  "trustedFacets": [{
    "version": { "major": 1, "minor" : 0 },
    "ids": [
        "https://login.example.com",
        "https://secure.example.com",
        "android:apk-key-hash:585215fd5153209a7e246f53286035838a0be227"
    ]
  }]
}

CLS Descriptor: Property "serviceDesc.loginUseRules"

Type Object. Required.

Specifies the extended UserLogin information.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      "baseSapId": "example.com/some/manifest.json",
      "loginUseRules": {
        "altSapIdList": [ {"id":"login.example.com/manifest2.json", "colType":"SSO"},
          {"id":"example.com/manifest3.json", "colType":"SSO"} ]
      },
      "userAuthenticationRequirements": {
        "allowedScope": {"rpMatch": [{"id":"example2.com", "all-subdomains":"yes"}]}
      },
      ...
    serviceItemEnd}
  ]
}

CLS Descriptor: Property "serviceDesc.loginUseRules.altSapIdList"

The list of "Foreign Login Sources" supported by the RP. That is, the list of Foreign RP from which the RP is willing and able to use a Login Item to authenticate the user.

The RP may have the ability to receive and process login information that belongs to a Foreign RP. That is, UserLogins that belong to the Foreign RP website and are normally used to login the user to that website.

For websites that want to share login credentials. To allow the user to login to one website with the username and credentials for a different website. For example, a set of websites may only have one username and set of credentials for a user. (All are shared for the websites in the group). This is also useful if a website changes its domain name. The new website can continue to use the same logins as the old website.

Contains two lists. (1) "altSapIdList" is other rp that are alternate sources for credentials. (2) "allowedScope" contains Foreign RP that are allowed to use this RP's credentials.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      "baseSapId": "example.com/some/manifest.json",
      "loginUseRules": {
        "altSapIdList": [ {"id":"login.example.com/manifest2.json", "colType":"SSO"},
          {"id":"example.com/manifest3.json", "colType":"SSO"} ]
      },
      "userAuthenticationRequirements": {
        "allowedScope": {"rpMatch": [{"id":"example2.com", "all-subdomains":"yes"}]}
      },
      ...
    serviceItemEnd}
  ]
}

CLS Descriptor: Property "serviceDesc.userAuthenticationRequirements.allowedScope" (longName: "Permit Sharing With RP")

Type Object.

Contains the Foreign RP sharing rules.

The "rpMatch" is the list of Foreign RP that this RP allows its logins to be shared with. This authorizes the Foreign RP to use Logins from this RP as a "Foreign Login Source".

The Foreign RP must also list this RP as one of the "supported Foreign Login Source". So that it can ask its users to login using logins from this RP.

For websites that want to share login credentials. To allow the user to login to OTHER websites with the username and credentials for THIS RP.

Contains a list. (2) Other rp that are allowed to use this rp's credentials.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      "baseSapId": "example.com/some/manifest.json",
      "loginUseRules": {
        "altSapIdList": [ {"id":"login.example.com/manifest2.json", "colType":"SSO"},
          {"id":"example.com/manifest3.json", "colType":"SSO"} ]
      },
      "userAuthenticationRequirements": {
        "allowedScope": {"rpMatch": [{"id":"example2.com", "all-subdomains":"yes"}]}
      },
      ...
    serviceItemEnd}
  ]
}

CLS Descriptor: Property "serviceDesc.mediation"

Type string.

Specifies if the RP requires user presence and approval.

If the service requires user intervention.

Options are: "silent", "optional", "required"

Example ClientConfig HTML:
<link href="/_capis/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "endpoint":{"sUri":"/_capis/cls/serviceCall.json", "http_method":"POST", "parameterList": [{"name":"capis_request"}],
  "request_format": "JWS"},
  "mediation": "required",
  }] '/>

CLS Descriptor: Property "serviceDesc.cls.serviceDesc.displayInfo" (longName: "fubar")

Type Object.

Specifies custom names and icons for the site. Can be displayed to the user in the identity login box.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png",
    "siteName": "123done",
    "siteLogo": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "protocol": "capis_login_service",
      "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
      "displayInfo": {
        "loginIcon": "/images/logo.png"
      }
    serviceItemEnd}
  ]
}

CLS Descriptor: Property "serviceDesc.userIdRules"

Type Object. Default value: {"createMethods":["assigned_ulc"]}

Specifies the "User Login creation" options that the RP supports. The values must be from the UserLogin Creation Methods. (Used with the "createUserLogin" opId.) Used in the CLS Request.user_login_creation_method value.

Specifies the Single-site UserId to use during User Login creation. (i.e. When registering the user.) The value must be one of the set of UserId created by the RP, and given to the browser to choose from.

This value is used by the requested_ulc UserLogin Creation Method.

TODO, WARNING: THE genMethods PROPERTY MAY BE REMOVED. This property really isn't needed.

<link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required", "userIdRules": {"genMethods":["st1","ct1"]} }] '/> ... <form ... handling="capis-trigger" capis-config=' "serviceOp":"cls/signData", "userIdRuleCfg": { "genMethods": ["st1","ct1"] }, "setUserIdRuleCfgByFieldId":"input27" '> <input type="text" name="user_email" value="john@example.com" placeholder="Enter your email address" /> <input id="input27" type="text" value='{ "genMethods": ["st1","ct1"] }' /> </form>

The "userIdRules" value is an object. The object can have the "genMethods" property. The "st1" value means "server timestamp format #1". The "ct1" value means "client timestamp values format #1"

The CLS Descriptor userIdRules value tells the browser what the RP's rules are. The CLS TriggerConfig userIdRuleCfg asks the RP to change its default behavior.

This property is used to specify a Single-site UserId. (As opposed to a Locked Id.) Therefore, it is only used when the RP supports both User Login creation and account login using Single-site UserIds. (Which is the default.) Specifically, the RP must support Single-site UserIds (i.e. the "single_site_userId" userIdRules.userIdTypes), and it must be capable of storing Credential Verification Rules (i.e. the "stored_cred" supported.userAuthScheme).

With this configuration option, the RP can provide help to the user when choosing a Single-site UserId, or validate the UserId, before the browser sends the "authentication request" to the RP.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      "baseSapId": "example.com/some/manifest.json"
      "userIdRules": {
        "userIdTypes": ["single_site_userId"],
        "createMethods": ["assigned_ulc", "claim_ms_ulc"]
      },
      "loginUseRules": {
        "altSapIdList": [ {"id":"login.example.com/manifest2.json", "colType":"SSO"},
          {"id":"example.com/manifest3.json", "colType":"SSO"} ]
      },
      "supported": {
      }
    serviceItemEnd}
  ]
}

CLS Descriptor: Property "serviceDesc.userIdRules.userIdTypes"

Type Array(). Default value: ["single_site_userId"]

Specifies the list of "user identifier types" the RP supports. For use in the UserId. Default is ["single_site_userId"].

An "identifier type" can be either one of the defined values (i.e. "single_site_userId"), or it can be a CIQ type specifier. (i.e. contain "ciq", a namespace and type.) For example, either "single_site_userId" or "ciq:C:B1:9:ri", etc. An RP can choose to trust only CIQ identifiers with a particular namespace. Or it can only trust those in a namespace that also have a certain subtype (such as "ciq:C:B1:9:ri"), etc.

The value is also used in the UserLogin Creation Methods. When the "claim_ms_ulc" serviceDesc.userIdRules.createMethods is used. It limits what type of identifier can be used to identify a user at the RP.

Values include "single_site_userId", "ciq:C:B1:9:ri", "federated", etc.

(Used by the "CLS Request.uic.format" property.)

Example: ["single_site_userId", "ciq:C:B1:9:ri", ...]

single_site_userId value:

The "single_site_userId" setting means that the RP supports browsers sending a "Single-site UserId" to login. (As opposed to a Locked Id.) This means that the RP MUST be capable of storing some sort of Credential Verification Rule for the users. (a password, or public key, etc.) When the RP receives the "proof of identity", it will validate the proof using the Credential Verification Rule stored for the claimed UserId. (If there are any.)

The "single_site_userId" means that the RP is capable of storing "CVR" values for the user. Therefore, the RP does not have to exclusively rely on the Locked Id lock. i.e. The user verification process. (The RP can add CVR to any UserId type, single-site, federated or Self-contained.) The RP (1) accepts Single-site UserIds and (2) stores Credential Verification Rule for users.

CLS Descriptor: Property "serviceDesc.userIdRules.createMethods"

Type Array(). Default value: ["assigned_ulc"]

Specifies a list of "User Login creation" methods the RP supports. (Used with the "createUserLogin" opId.) Used in the CLS Request.user_login_creation_method value.

See UserLogin Creation Methods for a list of the possible values.

Valid values are "assigned_ulc", "claim_ms_ulc", "requested_ulc" etc.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      "baseSapId": "example.com/some/manifest.json"
      "userIdRules": {
        "userIdTypes": ["single_site_userId"],
        "createMethods": ["assigned_ulc", "claim_ms_ulc"]
      },
      "loginUseRules": {
        "altSapIdList": [ {"id":"login.example.com/manifest2.json", "colType":"SSO"},
          {"id":"example.com/manifest3.json", "colType":"SSO"} ]
      },
      "supported": {
      }
    serviceItemEnd}
  ]
}

CLS Descriptor: Property "serviceDesc.supported"

Type Object. Required.

The section containing all the protocols, etc. that the RP supports.

Contains the protocols, etc. that are supported.

CLS Descriptor: Property "serviceDesc.supported.userAuthScheme"

Type Array(). Default value: ["only_MSUID"]

Specifies a list of "CapisLogin UA methods" that the RP supports. See the Login Method List. For example, "stored_cred".

The values in this property are used by the "user_auth_method" property.

This property lists what authentication methods can be used to login to the RP.

CLS Descriptor: Property "serviceDesc.supported.uic"

Type Object.

Specifies a UserId certificate information object.

CLS Descriptor: Property "serviceDesc.supported.uic.format" (longName: "supported.uic.format")

Type Array(). Default value: ["JWS"]

TODO. MAY_BE_REMOVED. Identity certificates are only used when a person uses a "federated user identifier". (i.e. A type of Locked Id that uses an "identity provider".)

Specifies a list of the "UserId certificate formats" the RP supports. RPs must support at least "JWS".

(Used by the CLS Request.uic.format property.)

Values include "JWS-CS" ("JWS-Compact Serialization"), "JWE-CS" (JWE-Compact Serialization), "JWS" (Long form JWS-JSON), "chain_42".

If "chain_42" is used, then the "uic.ucv" is not used, and the "user_id_certificate_chain" is used instead.

CLS Descriptor: Property "serviceDesc.supported.uic.csvm" (longName: "supported.uid_cert.sig_ver_method")

Type Array(). Default value: ["basic1"]

TODO. MAY_BE_REMOVED. Identity certificates are only used when a person uses a "federated user identifier". (i.e. A type of Locked Id that uses an "identity provider".)

Specifies a list of "UserId certificate signature verification methods" the RP supports. RPs must support at least "basic1".

(Used by the CLS Request.uic.csvm property.)

The RP uses the "supported.uic.csvm" value in an attempt to verify the UserId certificate. To do this, typically the RP must get a list of signature verification keys from the issuer of the certificate. This is to verify the UserId certificate actually was signed by the issuer. Thus, in a lot of cases, the "supported.uic.csvm" value is used for Certificate Signature Verification Protocol.

Valid values are "basic1", "basic2". (These include "OIDCD" and "BrowserID".)

TODO MAY_BE_REMOVED (X.509 certificate chain and thumbprints, JSON web key and url, etc.) Prefix an entry with "-" (minus sign, dash) to drop support for it. (Example: "supported.uic.csvm": ["basic2","-basic1"]

CLS Descriptor: Property "serviceDesc.supported.credentialProofItem.formats" (longName: "supported.credentialProofItem.formats")

Type Array(). Default value: ["TBD-CPF"]

Specifies a list of the Credential Verification Rule "formats" the RP supports. RPs must support at least "TBD-CPF".

(Used by the CLS Request.credentialProofItem.format property.)

It is expected that this attribute is rarely used, as the default will suffice. However, it is here in case an RP wants to use something else.

Known values are "TBD-CPF" and "fmt_cert_42".

CLS Descriptor: Property "serviceDesc.supported.credentialReg.ruleTypes"

Lists the types of Credential Verification Rule that the RP can store for users. (The CLS Request.credentialVRItem.type (typ) property should be one of these values.)

Valid values are "password", "pubkey", "federated".

(CVR types define types of CVR. User Identifier Types define types of identifiers.)

CLS Descriptor: Property "serviceDesc.supported.credentialReg"

Type Object. Default value: {"publicKeyTypes":[{"name":"pubkey_s1", "JWA_alg":"ES256", "storageQuantity":"1"}]}

Lists the "Credential Verification Rule" types and number that the RP can store for users.

Valid property names are "supported.credentialReg.passwordTypes", "supported.credentialReg.publicKeyTypes", "supported.credentialReg.federatedTypes", "HOTP", "TOTP".

"password" uses the "supported.credentialReg.passwordTypes. HOTP protocol.

{
  "id": "service_1",
  "protocol": "capis_login_service",
  "endpoints": [
    { "id":"endpoint_1", "sUri":"/_capis/cls/serviceCall", "request_format":"JWS" }
  ],
  "userIdRules": {
    "userIdTypes": ["single_site_userId", "ciq:C:B1:9:ri"],
    "createMethods": ["assigned_ulc", "claim_ms_ulc"]
  },
  "supported": {
    "credentialReg": {
      "ruleTypes": {"pubkey":"1"},
      "passwordTypes": [{"name":"password_s1", "maxLength":14, "storageQuantity":"1"}],
      "publicKeyTypes": [{"name":"pubkey_s1", "JWA_alg":"ES256", "storageQuantity":"1"}],
      "required_ruleTypes": {"pubkey1":"1"}       // The RP requires a "public key" authentication.
    },
    "userAuthScheme": {"methods":["stored_cred", "only_MSUID"]},
    "supported.uic.csvm": ["basic1", "basic2"]
  },
  "requirement_section": {}
}

CLS Descriptor: Property "serviceDesc.supported.credentialReg.passwordTypes"

Type Object.

Lists the "Credential Verification Rule" "password" type and number that the RP can store for users.

CLS Descriptor: Property "serviceDesc.supported.credentialReg.publicKeyTypes"

Type Object. Default value: {"size":"1"}

Lists the "Credential Verification Rule" "pubkey" type and number that the RP can store for users.

Valid properties are "size". An RP can declare it does NOT support storing any public keys for the user by either setting "size": "0" or setting "pubkey":{}.

CLS Descriptor: Property "serviceDesc.supported.credentialReg.publicKeyTypes.JWA_alg"

Type Object. Default value: "ES256"

The JWK algorithm of the public key Credential Verification Rule being sent to the RP in the CVR section.

Valid values are "ES256", "RS256", "RS384", "RS512". See CLS Request.JWS.sig_alg and COSE_alg.

CLS Descriptor: Property "serviceDesc.supported.credentialReg.federatedTypes"

Type Object.

Lists the "Credential Verification Rule" "federated" type and number that the RP can store for users.

See federated credential.

CLS Descriptor: Property "serviceDesc.supported.credentialReg.required_ruleTypes"

Type Object.

The type and number of "Credential Verification Rule" that the RP REQUIRES.

Valid property names are whatever types are defined in "supported.credentialReg". Examples are: "pubkey1", "password1", "federated1".

Tells the browser what the RP requires that the "proof of identity" contain. A common "required" Credential Verification Rule (CVR) is a public key. A "supported public-key" CVR means that the RP must be able to store a "public key" for each of its users. (Should a user choose to sign-in with a public key.) Being a "required" CVR means that the RP requires the user to send a digital signature signed by the private key. (Provides additional security.)

CLS Descriptor: Property "serviceDesc.supported.credentialReg.required_ruleTypes.pubkey1"

Type Object. May be Required?.

CLS Descriptor: Property "serviceDesc.supported.factor2"

Type Array().

Specifies the types of 2nd factor authentication that are supported. If the attribute is omitted, no 2nd factor is supported. The most common value is "JWT". Used to support a 2nd authentication form. Tells the browser to submit a second JWT, signed by the user's private key for the RP.

CLS Descriptor: Property "serviceDesc.required"

Type Object.

The section containing all the protocols, etc. that the RP requires.

Contains the protocols, etc. that are required.

CLS Descriptor: Property "serviceDesc.requirement_section.factor2"

Type string.

Specifies the type of 2nd factor authentication required. If the attribute is omitted, no 2nd factor is required. The most common value is "JWT". Used to require a 2nd authentication form. Tells the browser to submit a second JWT, signed by the user's private key for the RP.

CLS Descriptor: Property "serviceDesc.userAuthenticationRequirements"

Type Object. Required.

Specifies the RP requirements for authenticating a user. i.e. This lists the RP requirements for creating and modifying a User Login.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      ...
      "userAuthenticationRequirements": {
        "comment_21": "Each loginConfiguration details the number and type of credentials required for that configuration.",
        "loginConfigurations": [
          { "id": "cfg1", "allow": "always", "credentialInfoList": [
            {"type":"module", "mid":"pubKeyFirst"} ]
          },
          { "id": "cfg2", "allow": "always", "credentialInfoList": [
            {"type":"module", "mid":"passwordCred2"} ]
          }
        ],
        "credentialInfoModules": [
          { "id": "passwordCred2", "allow": "always", "credentialInfoList": [
            { "type":"password", "transport":"raw" } ]
          },
          { "id": "pubKeyFirst": "allow": "always", "credentialInfoList": [
            { "type":"public-key", "COSE_alg": -7 },
            { "type":"public-key", "COSE_alg": -257 } ]
          }
        ],
        "allowedScope": {"rpMatch": [{"id":"12doors.com/test1", "all-subdomains":"yes"}]}
      }
    serviceItemEnd}
    ...
  ]
}

CLS Descriptor: Property "serviceDesc.loginConfigurations"

Type Object. Required.

An array of loginConfiguration objects. Each loginConfiguration object details the requirements for authenticating a user.

The credentialInfoList contains credentialInfo items. These items can have a "type" that is one of "public-key", "password", "federated", or "module". The "module" value means that the credentialInfo definition exists in a different place, in the credentialInfoModules.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      ...
      "userAuthenticationRequirements": {
        "comment_21": "Each loginConfiguration details the number and type of credentials required for that configuration.",
        "loginConfigurations": [
          { "id": "cfg1", "allow": "always", "credentialInfoList": [
            {"type":"module", "mid":"pubKeyFirst"} ]
          },
          { "id": "cfg2", "allow": "always", "credentialInfoList": [
            {"type":"module", "mid":"passwordCred2"} ]
          }
        ],
        "credentialInfoModules": [
          { "id": "passwordCred2", "allow": "always", "credentialInfoList": [
            { "type":"password", "transport":"raw" } ]
          },
          { "id": "pubKeyFirst": "allow": "always", "credentialInfoList": [
            { "type":"public-key", "COSE_alg": -7 },
            { "type":"public-key", "COSE_alg": -257 } ]
          }
        ],
        "allowedScope": {"rpMatch": [{"id":"12doors.com/test1", "all-subdomains":"yes"}]}
      }
    serviceItemEnd}
    ...
  ]
}

CLS Descriptor: Property "serviceDesc.credentialInfoModules"

Type Object. Required.

An array of credentialInfoModule objects. Each credentialInfoModule object details one of the credential requirements, for authenticating a user.

The credentialInfoList contains credentialInfo items. These items can have a "type" that is one of "public-key", "password", "federated".

Example see loginConfigurations:
{
}

CLS Descriptor: Property "serviceDesc.credentialCreationOptions"

Type Object. Default value: {(see details)}

Lists the options for creating a credential. (i.e. a Credential Verification Rule.)

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      ...
      "credentialCreationOptions": {
        "publicKeyCredentialCreationOptions": {
          "comment_0a": "Note that both the 'rp' and 'user' properties of Webauthn have been moved.",
          "comment_0b": "The 'rp' section was MOVED to root:'service_info'. The 'user' values MOVED to the 'capis-config' HTML attribute.",
          "comment_1": "rp is of type PublicKeyCredentialRpEntity (Relying Party)",
          "comment_2": "user is of type PublicKeyCredentialUserEntity",
          "comment_2b": "The id field in user, will be automatically converted into a Uint8Array.",
          "comment_2c": "id conversion is: Uint8Array.from(window.atob(id), c=>c.charCodeAt(0))",
          "comment_3": "pubKeyCredParams is an array of type PublicKeyCredentialParameters. THe order is important.",
          "comment_3b": "This Relying Party will accept either an ES256 or RS256 credential, but prefers an ES256 credential.",
          "comment_3bb": "COSE_alg is a COSEAlgorithmIdentifier",
              "comment_3c": "-7 is the value for ES256. As registered in the IANA COSE Algorithms registry",
              "comment_3d": "-257 is the value for RS256. As registered by the WebAuthn specification",
          "comment_4": "timeout is of type unsigned long. 60000 milliseconds = 1 minute",
          "comment_5": "excludeCredentials is an array of type PublicKeyCredentialDescriptor",
          "comment_5b": "In this example, there is No exclude list of PKCredDescriptors",
          "comment_6": "extensions is of type UserAuthenticationExtensionsClientInputs",
          "comment_6b": "An extension of {loc:true} means Include location information in attestation.",
          "comment_7": "attestation is of type AttestationConveyancePreference. values are none, direct, indirect",
          "comment_8": "authenticatorSelection is of type AuthenticatorSelectionCriteria",
        
          "rp_REMOVED": {
            "name": "ACME Corporation",
            "icon": "http://example.com/some/path/icon.png",
            "id": "https://login.example.com"
          },
        
          "user_REMOVED": {
            "id_comment": "id is of type BufferSource. id will be converted. Uint8Array.from(window.atob(id), c=>c.charCodeAt(0))",
            "id": "MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII=",
            "name": "alex.p.mueller@example.com",
            "displayName": "Alex P. Müller",
            "icon": "https://pics.example.com/00/p/aBjjjpqPb.png"
          },
        
          "pubKeyCredParams": [
            {
              "type": "public-key",
              "COSE_alg": -7
            },
            {
              "type": "public-key",
              "COSE_alg": -257 
            }
          ],
        
          "timeout": 60000,
          "excludeCredentials": [],
          "extensions": {"loc": true},
          "attestation": "none",
          "authenticatorSelection": {
            "authenticatorAttachment": "platform",
            "residentKey": "required",
            "requireResidentKey": false,
            "userVerification": "preferred"
          }
        }
      }
    serviceItemEnd},
    { "id": "service_2",
    }
  ]
}

CLS Descriptor: Property "serviceDesc.credentialRegistration_temp"

Type Object.

Lists the options for creating a Public Key credential.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      ...
      "credentialRegistration": {
        "publicKey_CR": {
           "pubKeyCredParams": [
            {
              "type": "public-key",
              "COSE_alg": -7
            },
            {
              "type": "public-key",
              "COSE_alg": -257 
            }
          ],
        
          "timeout": 60000,
          "excludeCredentials": [],
          "extensions": {"loc": true},
          "attestation": "none",
          "authenticatorSelection": {
            "authenticatorAttachment": "platform",
            "residentKey": "required",
            "requireResidentKey": false,
            "userVerification": "preferred"
          }
        }
      }
    serviceItemEnd},
    { "id": "service_2",
    }
  ]
}

CLS Descriptor: Property "serviceDesc.credentialRegistration.pubKey.JWA_alg"

Type string. Default value: "ES256"

Lists the options for creating a Public Key credential.

CLS Descriptor: Property "serviceDesc.credentialRegistration.pubKey.cci"

Type integer. Default value: none

Lists the options for creating a Public Key credential.

CLS Descriptor: Property "serviceDesc.credentialRegistration.pubKey.type"

Type string. Default value: none

Lists the options for creating a Public Key credential.

CLS Descriptor: Property "serviceDesc.credentialRegistration.pubKey.COSE_alg"

Type integer. Default value: -7 (i.e. JWA "ES256".)

Lists the options for creating a Public Key credential.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      ...
      "credentialRegistration": {
        "publicKey_CR": {
           "pubKeyCredParams": [
            {
              "type": "public-key",
              "COSE_alg": -7
            },
            {
              "type": "public-key",
              "COSE_alg": -257 
            }
          ],
        
          "timeout": 60000,
          "excludeCredentials": [],
          "extensions": {"loc": true},
          "attestation": "none",
          "authenticatorSelection": {
            "authenticatorAttachment": "platform",
            "residentKey": "required",
            "requireResidentKey": false,
            "userVerification": "preferred"
          }
        }
      }
    serviceItemEnd},
    { "id": "service_2",
    }
  ]
}

CLS Descriptor: Property "serviceDesc.credentialAssertionOptions"

Type Object.

Lists the options for creating a credential assertion.

{
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "ACME Corporation",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [
    {serviceItemStart
      "id": "service_1",
      "protocol": "capis_login_service",
      ...
      "credentialAssertionOptions": {
        "publicKeyCredentialRequestOptions": {
          "comment_1": "rpId is of type USVString",
          "comment_2": "timeout is of type unsigned long. 60000 milliseconds = 1 minute",
          "comment_3": "allowCredentials is an array of type PublicKeyCredentialDescriptor.",
          "comment_3b": "The id fields in allowCredentials, will be automatically converted into a Uint8Array.",
          "comment_3c": "id conversion is: Uint8Array.from(window.atob(id), c=>c.charCodeAt(0))",
          "comment_3d": "allowCredentials item, transports values are usb, nfc, ble",
          "comment_3e": "allowCredentials item can omit the id field? Example 8 in webauthn",
          "comment_5": "userVerification is of type UserVerificationRequirement",
          "comment_6": "extensions is of type UserAuthenticationExtensionsClientInputs",
     
          "rpId_REMOVED": "12doors.com",
          "timeout": 60000, 
          "allowCredentials": [
            { "type":"public-key" },
            { "type":"public-key", "id":"!!!!!!!hi there!!!!!!!\n" },
            { "type":"public-key", "id":"roses are red, violets are blue\n" },
            { "type":"public-key", "transports": [] }
          ],
          "userVerification": "preferred",
          "extensions": {
            "txAuthSimple": "Wave your hands in the air like you just don’t care",
            "webauthnExample_foobar": 42
          }
        }
      }
    serviceItemEnd},
    { "id": "service_2",
    }
  ]
}

CLS Request Detail

The Capis Login Service Request (CLS Request) is a communication from the browser to the RP service endpoint. It asks the RP to perform a user authentication service, such as "login", and it contains all the data needed for that purpose. It is a type of RP service request. It consists of a single JSON object. The JSON contains a JSON Web Signature. The RP will send a CLS Response in response to the request.

In general, the CLS Request is used to transmit a "proof of identity", along with any other necessary data, to the RP. Using a JWS allows all the data to be cryprographically signed, with multiple signatures. The signatures can be verified by the RP. The payload of the JWS is used to store all the custom information. The payload values include a requested user authentication command (i.e. the reqOp). The reqOp value should contain a opId that is one of the CLS Operation List. (i.e. "login", "createUserLogin", "setActiveCredentials" etc.)

The browser sends the CLS Request to the "RP service endpoint" in whatever manner the RP designated in its CLS Service Descriptor. (i.e. In the Client Configuration Options, such as in the RP Config Document.) Usually the method is an HTTP POST. In the case where the CAPIS HTML Element that activated CAPIS is a form, and CAPIS is configured to send an HTTP POST, then the browser sends the service request as a special HTTP parameter *in addition to* any regular form data. The default name of the HTTP parameter is capis_request. See endpoint.parameterList.

Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "setActiveCredentials", "sub": "cls/setActiveCredentials", "iat": 1503971280, // issuedAt timestamp "exp": 1533064012, // expiresAt timestamp "aud": "RP_example.com", // the audience "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", // nonce value "nit": 1533064012, // nonceIssueTime "uid": { "raw": "ciq:C:A:3:X0s5eA:Aq", // The ciq UserId "ue1": "q3jC9-h", "usk": "q3jC9-h" }, "user_auth_method": "stored_cred", "redirectUri": "/some/path/page.html", "useCount": 42,
/* The user_id_certificate_chain is absent when using the "stored_cred" uauth_method. // user_id_certificate_chain "uic_chain": [ {"uic.format":"JWS", "uic.csvm":"YY", "ucv": { "payload":"82h7vb...", "signatures": [...] }} ], */
// crProofSection. "crProofSection": { "uid": { "raw2": "ciq:C:B1:2:xxxxxxxx", // The ciq UserId }, "uapCounter": 42, "aar": { // authenticatorAssertionResponse (optional) "adf": "WebAuthN 1.0", // authenticatorData_format "cda": "xxx", // clientDataJSON. Serialized JSON. "ada": "xxx", // authenticatorData. base64url encoded. "uha": "xxx" // userHandle. base64url encoded. }, "cpl": [ // credentialProofList { "cpid": "cd2", "cpt": "pubkey", "cpf": "TBD-CPF", // "credentialProofItem.format": "TBD-CPF" (not necessary. The default is "TBD-CPF".) "cpv": "mmmm" // base64url encoded JWT or signature. } ] }, // uac_registration. Required for "createUserLogin" and "setActiveCredentials" opId. "uac": { "backup_credentials": [ { "cvid": "cd-3", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { ... } } ], "cvrList": [ { "cvid": "cd10", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { "kty": "EC", "kid": "cd10", // "kid" is REQUIRED. Is the same as the "cvid". "crv": "P-256", "ext":true, "key_ops": ["verify"], "x": "5sy3ogiqTrlC_FF7aOdCq7cNFsN2nbrH4xQmNCCBtso", "y": "ctK7P_LU-SQPf-ejkmC1JYzm7S5N0B6ZX5rwOQWzuv8" }, "aof": "WebAuthN 1.0", // attestation_object_format "aod": "xxx" // attestation_object. base64url encoded. }, // If the RP allows 2 public keys as Credential Verification Rule. { "cvid": "cd11", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -257, "val": { "kty": "RSA", "kid": "cd11", // "kid" is REQUIRED. Is the same as the "cvid". "alg222": "RS256", "n" : "4b9e34...", "e" : "93bc32..." }, "aof": "WebAuthN 1.0", // attestation_object_format "aod": "xxx" // attestation_object. base64url encoded. } ] } }; let CLS Request = { "JWS": { "payload": BASE64URL(UTF8(payload_unencoded)), "signatures": [ { "protected": "eyJhbGciOiJFUzI1NiJ9", // protected_header = {"alg":"ES256", "sct":192} "header": { "kid": "cd1", "kid2": "e9bc097a-ce51-4036-9562-d2ade882db0d" // "kid": "userIdPK" // "userIdPK" means the public key is in "uid". }, "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga" } ] } }

CLS Request - List of Properties

Special JSON properties used in the "service request" JSON object

The following properties can be used in the "service request" JSON object. The following properties can be used in the "payload" JSON object.

CLS Request: Property "requestData.JWS" (longName: "JWS")

Type Object. Required.

Contains a JSON Web Signature value. It is used as a UserId Assertion.

The JWS property contains a "JSON Web Signature" type of request. This is only one of the possible types of requests. Other types can be created in the future. JWE, etc. This allows the spec to be extended in the future. (For extensibility.)

Example CLS Request:
let CLS Request = {
  "JWS": {
    "payload": BASE64URL(UTF8(payload_unencoded)),
    "signatures": [
      { "protected": "eyJhbGciOiJFUzI1NiJ9",
        // protected_header = {"alg":"ES256", "sct":192}
        "header": {
          "kid": "cd1", "kid2": "e9bc097a-ce51-4036-9562-d2ade882db0d"
        // "kid": "userIdPK" // "userIdPK" means the public key is in "uid".
        },
        "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga"
      }
    ]
  }
}

CLS Request: Property "requestData.JWS.payload" (longName: "payload")

Type Object. Required.

Contains the data to be signed.

CLS Request: Property "requestData.JWS.signatureInfo" (longName: "signatureInfo")

Type Object. Required.

A single item in the signatures array. It represents a Credential Signature. Contains the signature. The signatures property contains an array of these items.

Example CLS Request:
let CLS Request = {
  "JWS": {
    "payload": BASE64URL(UTF8(payload_unencoded)),
    "signatures": [
      { "protected": "eyJhbGciOiJFUzI1NiJ9",
        // protected_header = {"alg":"ES256", "sct":192}
        "header": {
          "kid": "cd1", "kid2": "e9bc097a-ce51-4036-9562-d2ade882db0d"
        // "kid": "userIdPK" // "userIdPK" means the public key is in "uid".
        },
        "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga"
      }
    ]
  }
}

CLS Request: Property "signatureItem.header" (longName: "Signature unprotected header")

Type Object. Required.

Contains the "unprotected" signature header. This commonly includes the "key id" ("kid") against which the signature should be verified.

Contains the kid property.

CLS Request: Property "signatureItem.protected" (longName: "Signature protected header")

Type Object. Required.

Contains the "protected" signature header.

CLS Request: Property "signatureItem.protected.alg" (longName: "Signature Public Key Algorithm")

Type string. Required.

Contains the public key algorithm used to create the signature.

Suggested values: "RS256", "RS384", "RS512". See COSE_alg and CLS Descriptor.JWA_alg.

CLS Request: Property "signatureItem.protected.sct" (longName: "Signature Key Sign Count")

Type integer. May be required?

Contains the sign count. (Anti-forgery protection. Detect a cloned User Authenticator.)

CLS Request: Property "signatureItem.header.kid" (longName: "Signature Key ID")

Type string. Required when ?.

Contains the Key ID. Uniquely identifies the key for the UserLogin.

Key Id value: userIdPK[:n]

The string "userIdPK[:n]" can be used as the "kid" value in signature headers in the CLS Request. (Where 'n' is an integer from 1 to 100.) If it is used as the "kid" value, it notifies the RP that the signature was not created by a regular credential. Instead, the signature must be verified using the sig verification key of the public key encoded inside the "UserId". (i.e. In the "payload"."uid" value.)

Key Id value: certPK:n

The string "certPK:n" can be used as the "kid" value in signature headers in the CLS Request. (Where 'n' is an integer from 1 to 100.) If it is used as the "kid" value, it notifies the RP that the signature was not created by a regular credential. Instead, the signature must be verified using the sig verification key of the public key with the specified number from the UserId certificate.

CLS Request: Property "signatureItem.header.vkm" (longName: "sigInfo.header.sigVKMethod")

Type string. Required if the credential sig verification key is in the UserId Certificate. Default value: "site_stored_vks"

Used for Sig VK Method. See Set User Credential Verification Rules.

Values are site_stored_vks, userIdF and certificateF. Located in the unprotected signature header. (NOT THE SAME AS vkmc_value_list)

Ver Key Method value: site_stored_vks

The string "site_stored_vks" can be used

Ver Key Method value: userIdF

The string "userIdF" can be used as the "vkm" value in signature headers in the CLS Request. If it is used as the "vkm" value, it notifies the RP that the signature was not created by a regular credential. Instead, the signature must be verified using the sig verification key of the public key encoded inside the "UserId". (i.e. In the "payload"."uid" value.)

Ver Key Method value: certificateF

The string "certificateF" can be used as the "vkm" value in signature headers in the CLS Request. If it is used as the "vkm" value, it notifies the RP that the signature was not created by a regular credential. Instead, the signature must be verified using the sig verification key of the public key with the specified number from the UserId certificate.

CLS Request: Property "signatureItem.header.csvm" (longName: "sigInfo.header.certificateSigVKMethod")

Type string. Required if the JWT is a UserId Certificate.

Used for Certificate Signature Verification Protocol. See Set User Credential Verification Rules.

Located in the unprotected signature header.

CLS Request: Property "signatureItem.signature" (longName: "Signature")

Type string. Required.

Contains the actual signature value.

CLS Request: Property "requestData.signatures" (longName: "signatures[]")

Type Array(). Required.

An array of signatureInfo objects. An array of signatures inside a JWS (JSON Web Signature). These signatures are created by signing the payload with a set of private keys. The signatures are given to the RP in order to authenticate the JWS to the RP. When a CLS Request is composed of a JWS, the signatures will thereby authenticate the service request. A JWS supports multiple signatures. Therefore, a JWS service request is capable of Multiple Credential Authentication and Multi-Factor Authentication. (Each signature is proof of a different Credential Verification Rule. Each CVR may be a different factor.)

The CAPIS specification requires that each signature, except for one (for the "UserId"), MUST match a Credential Verification Rule that the RP stores for the UserId. Each signature MUST have a "kid" value (in the header section) that is the "Credential Verification Rule id" stored by the RP. (There may be less signatures than the number of CVR at the RP. The RP may have some CVR be optional, etc.)

There can be only one signature that does not directly represent a CVR stored at the RP. This is the signature from the UserId private key. The UserId private key signature will be always marked with a special "kid" value. ("kid": "userIdPK") The UserId private key signature is optional. (The RP may or may not require that user authentication requests be signed by it.) (This is for the case when the UserId contains or represents a public key. The UserId private key is the private key corresponding to the public one inside, or represented by, the UserId.)

Example CLS Request:
let CLS_Request = {
  "payload":
   "eyJpc3MiOiJq2bUiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF
    tcGxlLmNvbS9pc19yj290Ijp0cnVlfQ",
  "signatures": [
    { "protected": "eyJhbGciOiJSUzI1NiJ9",
        // protected_header = {"alg":"RS256", "sct":192}
      "header": {"kid":"cd1"},
      "signature":
       "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ
      mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb
      KBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHl
      t1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZES
      c6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AX
      LIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw"
    },
    { "protected": "eyJhbGciOiJFUzI1NiJ9",
        // protected_header = {"alg":"ES256", "sct":13}
      "header": {"kid":"cd2", "kid2":"e9bc097a-ce51-4036-9562-d2ade882db0d"},
      "signature":
       "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS
      lSApmWQxfKTUJqPP3-Kg6NU1Q"
    }
  ]
}

CLS Request: Property "payloadData.request_spec" (longName: "request_spec")

Type string. Default value: "capis 0.1"

The specification name and version that the CLS Request uses.

Valid values are "capis 0.1", etc.

CLS Request: Property "payloadData.protocolId" (longName: "protocolId")

Type string. Required.

The protocol of the operation to be performed by the RP. It is usually copied from the "serviceOp" property. (In the "capis-config" attribute.)

CLS Request: Property "payloadData.reqOp" (longName: "reqOp")

Type string. Required.

The requested operation to be performed by the RP. It is usually copied from the "serviceOp" property. (In the "capis-config" attribute.) It should contain a opId that is one of the CLS Operation List. (i.e. One of "login", "logout", "proveUserPresence", "createUserLogin", "grantAccess", etc.)

CLS Request: Property "payloadData.forSapId" (longName: "forSapId")

Type string. Required.

Specifies the Service Application Identifier (sapId) that the selected UserLogin is registered to. (i.e. the UserAuth ServiceApp) This is usually what website the UserLogin was registered to.

The forSapId is always always equal to the serviceDesc.baseSapId. The exception is when the user selects a foreignSap UserLogin to use (i.e. to login with).

CLS Request: Property "payloadData.uam" (longName: "user_auth_method")

Type string. Default value: "stored_cred"

Specifies how the request wants the RP to authenticate the user. (If it should require that "ownership" of the MSUID be verified. i.e. With a UserId certificate.)

See Login Method List for the list of valid values. Example: "stored_cred".

Used by the "supported.userAuthScheme" service property.)

CLS Request: Property "payloadData.iat" (longName: "issuedAt")

Type string. Required.

Indicates the timestamp when the request was generated.

CLS Request: Property "payloadData.exp" (longName: "expiresAt")

Type string. Required.

Indicates the timestamp when the request expires.

CLS Request: Property "payloadData.sub" (longName: "subject")

Type string. Required.

Indicates the subject of the request.

CLS Request: Property "payloadData.aud" (longName: "audience")

Type string. Required if the JWT is not a UserId certificate.

Indicates the intended audience of the request.

CLS Request: Property "payloadData.challenge" (longName: "challenge")

Type string. Required.

A "cryptographic nonce" value. base64url encoded. The value is passed back to the RP. Prevents cross site scripting (CSS) attacks. Copied from the config "challenge" option.

CLS Request: Property "payloadData.nit" (longName: "nonceIssueTime")

Type string. Required.

Indicates the timestamp when the challenge was generated.

CLS Request: Property "payloadData.redirectUri" (longName: "redirectUri")

Type string.

The URI the caller wants to be redirected to.

CLS Request: Property "payloadData.uid" (longName: "userId.mmm")

Type Object. Required.

The claimed UserId.

This is not the actual UserId, but a temporary UserId, used only in the current session. The actual UserId is kept secret from the browser. It is encrypted and sent to the RP in an encrypted form in the "login" request. (etc.)

When the reqOp is "createUserLogin", the browser should set the uid.timestamp_uid property. The RP will create a new assignedUserId and send it to the browser in an encrypted form. The browser should send it to the Login Manager, using LoginManager.setUserLoginDetails() in newProperties.updatedUserId. The Login Manager will decrypt the value and store it, associated with the login.

CLS Request: Property "payloadData.uid.raw" (longName: "userId.raw")

Type string. Required.

The raw UserId.

CLS Request: Property "payloadData.uid.ue1" (longName: "userId.encryption_value_1")

Type string. Required when serviceOp="cls/createUserLogin".

The encrypted UserId. Using encryption method 1.

The encrypted UserId and the sessionUserId are extra features to protect User Privacy. They both hide the real UserId from the browser. So that the user can use any browser and the UserId for all RP websites will remain secret from the browser.

The encrypted UserId is used when the browser is not logged into the RP website. In this case, the browser must send to the RP a secret, encrypted UserId. The UserId can be encrypted using the HTTP session encryption key or with the RP website HTTPS key.

If the browser is already logged into the RP website, then the browser does NOT send the encrypted UserId to the RP. In this case, it must send the sessionUserId instead. The sessionUserId is a temporary value the RP creates to "stand-in" for the real UserId.

CLS Request: Property "payloadData.uid.usk" (longName: "userId.sessionKey")

Type string. Required except when serviceOp="cls/createUserLogin".

The UserId session key. The value from sessionUserId.

The encrypted UserId and the "UserId session key" are extra features to protect User Privacy. They both hide the real UserId from the browser. So that the user can use any browser and the UserId for all RP websites will remain secret from the browser.

The encrypted UserId is used when the browser is not logged into the RP website. In this case, the browser must send to the RP a secret, encrypted UserId. The UserId can be encrypted using the HTTP session encryption key or with the RP website HTTPS key.

If the browser is already logged into the RP website, then the browser does NOT send the encrypted UserId to the RP. In this case, it must send the sessionUserId instead. The sessionUserId is a temporary value the RP creates to "stand-in" for the real UserId.

CLS Request: Property "payloadData.uid.timestamp_uid" (longName: "userId.timestamp_uid")

Type string. Required when serviceOp="cls/createUserLogin".

A raw UserId made from a timestamp. It is used with "createUserLogin" opId as a "service request id". The RP copies it into the response so that the browser will know what request is being responded to.

CLS Request: Property "payloadData.iss" (longName: "issuer")

Type string. Required if the JWT is a UserId certificate.

Indicates the Backer of the UserId.

CLS Request: Property "payloadData.pr.uid" (longName: "pr.userId.mmm")

Type Object. Required.

The claimed UserId.

CLS Request: Property "payloadData.pr.uid.raw2" (longName: "pr.userId.raw2")

Type string. Required.

The claimed UserId.

CLS Request: Property "payloadData.uid.uit" (longName: "userId.type")

Type string.

The type of the claimed UserId. Only necessary if the UserId is not written using "ciq" format.

Valid values are a CIQ type specifier. (i.e. the "ciq", namespace_id and lockType.) Examples: "ciq:C:B1:9", "ciq:C:A:3".

(Used by the "userIdRules.userIdTypes" service property.)

CLS Request: Property "payloadData.uid.clientReqUserId" (longName: "uid.clientReqUserId")

Type string.

The requested username to use when creating an account.

This property is only used with one of the "Negotiated UserId" UserLogin Creation Method. Such as "requested2_ulc".

This property name stands for "requested username". This property value is set from the CLS TriggerConfig.userIdRuleCfg property. This property is what the browser (or user) asks for. This is different from the CLS Descriptor.userIdRules, which contains the rules, and the default userId value that the RP provides.

See serviceDesc.userIdRules.

CLS Request: Property "payloadData.uid_cert_chain" ("icc") (longName: "UserId Certificate Chain")

Type Object. Required if the browser tries to authenticate with a Locked Id that uses a UserId certificate.

If "user_auth_method" is "only_MSUID", "combo_MSUID", or "certificate_2").

A JSON object containing an array of certificates. Each certificate is a JSON object.

(Note: If the UserId certificate is an X.509 certificate chain, then it can be stored in the UserId Assertion JWT header (in the CLS Request) as the "x5c" value. There does not have to be a separate "uid_cert_chain" property in this case.)

The UserId proof includes the "uic.ucv", "uic.format", and "uic.csvm" fields. These are part of the user_id_certificate_chain.

Example CLS Request:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "signData", "sub": "cls/signData", ... // user_id_certificate_chain (Available when not using the "stored_cred" uauth_method.) "uic_chain": [ {"uic.format":"JWS", "uic.csvm":"YY", "ucv": { "payload":"82h7vb...", "signatures": [...] }} ], ... }

CLS Request: Property "payloadData.uic.ucv" (longName: "uid_cert.value -- UserId Certificate")

Type Object. Required.

Contains an "UserId certificate". (Can be a JWT.) It is required, unless the "UserId certificate" is included in the UserId Assertion. For example, it could be an X.509 certificate and can be included in the UserId Assertion JWT as the "x5c" header property.

Example CLS Request:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "signData", "sub": "cls/signData", ... // user_id_certificate_chain (Available when not using the "stored_cred" uauth_method.) "uic_chain": [ {"uic.format":"JWS", "uic.csvm":"YY", "ucv": { "payload":"82h7vb...", "signatures": [...] }} ], ... }

CLS Request: Property "payloadData.uic.format" (longName: "uid_cert.format")

Type string. Default value: "JWS"

Specifies the format of "UserId certificate" in the "uic.ucv" property.

RPs must support at least the format "JWS" in the "supported.uic.format" service property.

Values include "JWS-CS" ("JWS-Compact Serialization"), "JWE-CS" (JWE-Compact Serialization), "JWS" (Long form JWS-JSON), "chain_42".

If "chain_42" is used, then the "uic.ucv" is not used, and the "user_id_certificate_chain" is used instead.

CLS Request: Property "payloadData.uic.csvm" (longName: "uid_cert.sig_ver_method")

Type string. Default value: "OIDCD"

Contains the "UserId certificate signature verification method". This value gives the RP information about how to verify the certificate. It is usually used to tell the RP how to get the sig verification key for the certificate. (i.e. it is usually used as input to Certificate Signature Verification Protocol.) However, the RP must first know the type of the certificate, and have the ability to read it.

(Used by the "supported.uic.csvm" service property.)

Valid values are:

The browser should choose to use an IDP and an "UserId certificate" that the RP can understand.

CLS Request: Property "payloadData.useCount" (longName: "useCount")

Type integer. Required.

Holds the use count. Holds the number of times the UserLogin has been used. Should always increase. (Anti-forgery protection. Detect a cloned User Authenticator.)

The UserLogin use counter. Holds the number of times the UserLogin has been used. Should always increase. Every use of the UserLogin to login should increment the counter. For extra security, the RP can record the count. If any subsequent login by the UserLogin uses an equal or lower value, then the UserLogin was compromised. (Attempts to detect if the User Authenticator is duplicated. Or the security device was copied, etc.)

CLS Request: Property "payloadData.gua" (longName: "grant_user_access")

Type Object. Required if serviceOp="cls/grantAccess".

The collection of information required in order to add, remove and modify a user's access to the account. Used by the Grant Access Service Action.

Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "grantAccess", "sub": "cls/grantAccess", ... // The grant_user_access section. "gua": { "backup_credentials": [ { "cvid": "cd-3", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { ... } } ], "cvrList": [ { "cvid": "cd10", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { "kty":"ES", "kid":"cd10", ... } } ] } }

CLS Request: Property "payloadData.prs" (longName: "credentialProofSection")

Type Object. Required if serviceOp="cls/createUserLogin" or "cls/setActiveCredentials".

The details of the user identity for an RP. Includes "id", credentialProofList ("cpl").

let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "login", // or "proveUserPresence" "sub": "cls/login", ... "iat": 1503971280, // issuedAt timestamp "exp": 1533064012, // expiresAt timestamp "aud": "RP_example.com", // the audience "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", // nonce value "nit": 1533064012, // nonceIssueTime "uid": { "raw": "ciq:C:A:3:X0s5eA:Aq", // The ciq UserId "ue1": "q3jC9-h", "usk": "q3jC9-h" }, "user_auth_method": "stored_cred", "redirectUri": "/some/path/page.html", "useCount": 42, ... // crProofSection. "crProofSection": { "uid": { "raw2": "ciq:C:B1:2:xxxxxxxx", // The ciq UserId }, "uapCounter": 42, "aar": { // authenticatorAssertionResponse (optional) "adf": "WebAuthN 1.0", // authenticatorData_format "cda": "xxx", // clientDataJSON. Serialized JSON. "ada": "xxx", // authenticatorData. base64url encoded. "uha": "xxx" // userHandle. base64url encoded. }, "cpl": [ { "cpid": "cd2", "cpt": "pubkey", "cpf": "TBD-CPF", // "credentialProofItem.format": "TBD-CPF" (not necessary. The default is "TBD-CPF".) "cpv": "mmmm" // base64url encoded JWT or signature. } ] }, ... }

CLS Request: Property "payloadData.prs.uapCounter" (longName: "uapCounter")

Type integer.

The number of times the LoginManager has been used to create a user authentication proof. (i.e. a proof of identity)

CLS Request: Property "payloadData.prs.cpl" (longName: "credentialProofList")

Type Array().

An array of credentialProofItem objects. This normally contains only proofs for credentials that are not public keys. The signatures property holds the proof for those credentials that are public keys. (If the CLS Request is not represented by a JWS, then the "credentialProofList" may hold public key credentials as well.) Each "credential proof" object can be of a different type.

The credential proofs are given to the RP in order to authenticate the user. Having the CLS Request contain multiple credential proof objects allows the RP to use Multiple Credential Authentication and Multi-factor authentication.

Each credential proof object has an "id", a "type", a "format", and a "value". The names of these properties are "cpid", "cpt", "cpf" and "cpv". The value is a string or a JSON object of a type specified by the format value. Each credential MUST normally have a "cpid" value, and the value MUST MATCH one of the "Credential Verification Rule id" values stored by the RP for the UserId. (There is only one exception. The "UserId" public key.)

There is one special case. One credential proof object is allowed to NOT refer to a CVR stored by the RP. In this case, the "cpid" must be set to the special value "userIdPK". ("cpid": "userIdPK") This marks the credential proof object as being the signature of the UserId private key. (This requires that the UserId be an encoded public key. See UserId.) Note that the UserId credential proof object is optional. An RP may or may not require it.

The RP stores "Credential Verification Rule" values for user authentication. The CVR values are given to the RP during (1) "createUserLogin" and (2) "Set Active Credentials" operations. The RP may not require all CVR. Some stored CVR may be optional, or the RP may require only a subset. The exact configuration is up to the RP. Because some CVR may be optional, the CLS Request may contain less credential proofs than the number of CVR at the RP. (The total number of credential proofs, in the cpl_list and the "signatures" array, may be less than the number of CVR stored by the RP.)

The credentialProofList also allows experiences that combine multiple authentication mechanisms such as fingerprint + PIN.

Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "login", // or "proveUserPresence" "sub": "cls/login", ... "useCount": 42, // crProofSection. "crProofSection": { "uid": { "raw2": "ciq:C:B1:2:xxxxxxxx", // The ciq UserId }, "uapCounter": 42, "aar": { // authenticatorAssertionResponse (optional) "adf": "WebAuthN 1.0", // authenticatorData_format "cda": "xxx", // clientDataJSON. Serialized JSON. "ada": "xxx", // authenticatorData. base64url encoded. "uha": "xxx" // userHandle. base64url encoded. }, "cpl": [ { "cpid": "cd2", "cpt": "pubkey", "cpf": "TBD-CPF", // "credentialProofItem.format": "TBD-CPF" (not necessary. The default is "TBD-CPF".) "cpv": "mmmm" // base64url encoded JWT or signature. } ] }, ... }

CLS Request: Property "payloadData.prs.credentialProofItem" (longName: "credentialProofItem")

Type Object.

A single item in the credentialProofList array. Represents a Credential Proof for a credential that is not a publicKey.

CLS Request: Property "payloadData.prs.credentialProofItem.cpid" (longName: "credentialProofItem.id")

Type string. Required.

Specifies the id of a credentialProofItem in the "credentialProofList". (Used with cls.request.uac.cvrList request property.)

The "cpid" value MUST MATCH the id (the "cvid") of one of the "Credential Verification Rule id" values stored by the RP for the UserId. (The "Credential Verification Rule" values were given to the RP during a previous "Set Active Credentials" operation.) (i.e. one of "cls/createUserLogin", "cls/setActiveCredentials".) The RP stores the "cvid", along with the CVR values. (The password or public key, etc.)

CLS Request: Property "payloadData.prs.credentialProofItem.cpt" (longName: "credentialProofItem.type")

Type string. May be Required?.

Specifies the type of a credentialProofItem in the "credentialProofList". (Used with supported.credentialReg.ruleTypes service property.)

Valid values are "password", "pubkey", "federated".

CLS Request: Property "payloadData.prs.credentialProofItem.cpv" (longName: "credentialProofItem.value")

Type string. Contains base64url encoded binary data. Required.

Specifies the value of a credentialProofItem in the credentialProofList array. Usually this is a JWT value. The format of the item is specified by the neighboring credentialProofItem.format parameter. The default credentialProofItem.format is "TBD-CPF".

If the CVR is a public key, then the credentialProofItem.value is usually a JWT, with a signature created by the private key.

CLS Request: Property "payloadData.prs.credentialProofItem.cpf" (longName: "credentialProofItem.format")

Type string. Default value: "TBD-CPF"

Specifies the format of a credentialProofItem.value in the credentialProofList array.

Values include "JWS-CS", "U2F", "sig". ("JWS-Compact Serialization"). (U2F is the standard of Universal 2nd Factor.)

If the value is "TBD-CPF", then the "credentialProofItem.value" is a "TBD-CPF". If the value is "fmt_cert_42", then the "credentialProofItem.value" is not used, and the "user_id_certificate_chain" is used instead. (That includes the "uic.ucv", "uic.format", and "uic.csvm" fields.)

The value the browser uses for "credentialProofItem.format" should be one of those supported by the RP. (One of those in the "supported.credentialProofItem.formats" property list.)

CLS Request: Property "payloadData.req_factor2" (longName: "req_factor2")

Type string.

Holds the 2nd factor authentication. (During User Login creation, the list of public keys. During login, the 2nd JWT.) When creating an account, the RP might allow additional public keys to be set. (2nd factor authentication) The public keys can be sent to the RP in an additional HTTP parameter. The keys can be in JWK format. When logging into an RP, the second signature can be sent to the RP in this second parameter. (As a JWT.)

CLS Request: Property "payloadData.cert.pubKeyList" (longName: "cert.pubKeyList")

Type Array(). Required if JWT is a UserId certificate.

Specifies the array of public keys in the UserId certificate.

CLS Request: Property "payloadData.cert.pubKey.pkf" (longName: "cert.pubKey.format")

Type string. Required if JWT is a UserId certificate.

Specifies the format of a public key in the UserId certificate.

CLS Request: Property "payloadData.prs.aar" (longName: "authenticatorAssertionResponse")

Type Object. Required when serviceOp="cls/createUserLogin" or "cls/setActiveCredentials".

A JSON object that specifies the exact bytes that the User Authenticator returned.

Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "setActiveCredentials", // or any serviceOp "sub": "cls/setActiveCredentials", ... "crProofSection": { ... "uapCounter": 42, "aar": { // authenticatorAssertionResponse (optional) "adf": "WebAuthN 1.0", // authenticatorData_format "cda": "xxx", // clientDataJSON. Serialized JSON. "ada": "xxx", // authenticatorData. base64url encoded. "uha": "xxx" // userHandle. base64url encoded. }, "cpl": [ // credentialProofList { "cpid": "cd2", "cpt": "pubkey", "cpf": "TBD-CPF", // "credentialProofItem.format": "TBD-CPF" (not necessary. The default is "TBD-CPF".) "cpv": "mmmm" // base64url encoded JWT or signature. } // End of credential entry. ] } // End of crProofSection. }

CLS Request: Property "payloadData.prs.adf" (longName: "authenticatorData_format")

Type string. Default value: "WebAuthN 1.0"

A string that specifies how the "authenticatorData" is encoded.

CLS Request: Property "payloadData.prs.cda" (longName: "clientDataJSON")

Type string. Contains base64url encoded binary data. Requirement unknown.

Holds the result of JSON stringifying and UTF-8 encoding to bytes a CollectedClientData dictionary.

Example JSON
{"type":"webauthn.create", "challenge":"MTIzNDU2Nzg", "origin":"RP_example.com", "tokenBinding":{"id":"m38hcBq"}}
Don't have any real idea what this should be. Look at webAuthn for ideas.
dictionary CollectedClientData {
    required DOMString           type;
    required DOMString           challenge;
    required DOMString           origin;
    TokenBinding                 tokenBinding;
};

CLS Request: Property "payloadData.prs.ada" (longName: "authenticatorData")

Type string. Contains base64url encoded binary data. Required if serviceOp="cls/createUserLogin" or "cls/setActiveCredentials".

Base64url encoded binary data. Holds the data from the User Authenticator.

Don't have any real idea what this should be. Look at webAuthn for ideas.
dictionary ParsedAuthenticatorData {
    ArrayBuffer (32 bytes) rpIdHash; // A hash of the rpId string.
    ArrayBuffer (1 bytes) flags;
    // MOVED signCount; (Number) Moved to useCount.
    // MOVED attestedCredentialData; (Object. optional) Moved to attestation_object.
    extensions; (Object. optional)
};

CLS Request: Property "payloadData.prs.uha" (longName: "loginItem_userHandle")

Type string. Contains base64url encoded binary data. Requirement unknown.

Base64url encoded binary data. Holds an opaque user handle.

CLS Request: Property "payloadData.uac" (longName: "uac_registration")

Type Object. Required if serviceOp="cls/createUserLogin" or "cls/setActiveCredentials".

The collection of User Authentication Credentials to be stored by the RP. Used when the serviceOp is either "createUserLogin" or "setActiveCredentials.

It contains the list of Credential Verification Rule to be stored by the RP. (i.e. the "cvrList") (Each entry in the "removeList" contains two items, "cvid" and "typ".) Each entry in the "cvrList" contains at least 4 items, "cvid", "typ", "fmt" and "val". The data may be passwords or public keys, etc.

Valid properties are "cvid" = "credential verification id", "typ" = "type", "fmt" = "format", "val" = "value"

Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "setActiveCredentials", // or "createUserLogin" "sub": "cls/setActiveCredentials", ... // The uac_registration "uac": { "backup_credentials": [ { "cvid": "cd-3", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { ... } } ], "cvrList": [ { "cvid": "cd10", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { "kty":"ES", "kid":"cd10", ... }, "aof": "WebAuthN 1.0", // attestation_object_format "aod": "xxx" // attestation_object. base64url encoded. } ] } }

CLS Request: Property "payloadData.user_login_creation_method" (longName: "user_login_creation_method")

Type Array(). Required if serviceOp="cls/createUserLogin". Default value: "assigned_ulc"

It is a member of the uac_registration section.

The value is one of those from UserLogin Creation Methods. Such as claim_ms_ulc, assigned_ulc. The value has to be one of those supported by the RP. See serviceDesc.userIdRules.createMethods.

CLS Request: Property "payloadData.uac.bkcr" (longName: "backup_credentials")

Type Array(). Required if serviceOp="cls/createUserLogin" or "cls/setActiveCredentials".

It is a member of the uac_registration section.

Provides a backup way to verify the user's identity. It exists in case the primary public key (in the UserId) is compromised. The public key is also used when verifying an "identity change request". When the user tries to change their identity. (The backup is also verified in case the user's primary public key has been compromised.) This backup key is given to the RP in the CLS Request (that uses the "createUserLogin" opId) when creating an account at the RP. The RP should permanently keep the key. It provides an additional way to verify the user. It is only used to verify the user for a few extreme cases.

When the user wants to change the UserId, he must provide an "identity change request" key. The RP must ensure that the change request is performed by the user. The request must be signed with a signature from the private key linked to the "backup_credentials".

CLS Request: Property "payloadData.uac.cvrList" (longName: "uac.credentialVRList")

Type Array(). Required.

An array of credentialVRItem objects. Each item represents a Credential Verification Rule to be stored by the RP. The list is expandable, to hold any number of credentials. See CLS Request: Set Credential Verification Rules Detail.

It is a member of the uac_registration section.

CLS Request: Property "payloadData.uac.cvrItem" (longName: "credentialVRItem")

Type Object.

A single item in the cvrList array. (In the "uac_registration" section.) It represents a Credential Verification Rule.

Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "setActiveCredentials", // or "createUserLogin" "sub": "cls/setActiveCredentials", ... // The uac_registration "uac": { "backup_credentials": [ { "cvid": "cd-3", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { ... } } ], "cvrList": [ { "cvid": "cd10", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { "kty":"ES", "kid":"cd10", ... }, "aof": "WebAuthN 1.0", // attestation_object_format "aod": "xxx" // attestation_object. base64url encoded. } ] } }

CLS Request: Property "payloadData.uac.cvrItem.cvid" (longName: "credentialVRItem.id")

Type string. Required.

The identifier of a Credential Verification Rule being sent to the RP in the "uac_registration" section.

During login, each of the "cpid" values sent to the RP (by the user's Login Manager) MUST MATCH the id (the "cvid") of one of the "Credential Verification Rules" stored by the RP for the user.

During one of the "Set Active Credentials" commands, the user's "Login Manager" sends a list of "credentialVR" items (i.e. the "cvrList") to the RP. It can set the "cvid" values to whatever it likes, with the following restrictions. Each value must be unique within the scope of the cvrList. Limited to alpha-numeric, dash and underscore characters. (allows base64url encoding). Maximum of 16 characters. The first character must be "c".

This value is NOT supplied by the RP. It is supplied by the browser. It is used during one of the "Set Active Credentials" commands. (i.e. one of "cls/createUserLogin", "cls/setActiveCredentials".) The RP stores the "cvid" value, along with the actual CVR value. (The password or public key, etc.)

CLS Request: Property "payloadData.uac.cvrItem.typ" (longName: "credentialVRItem.type")

Type string. May be Required?.

The type of a Credential Verification Rule being sent to the RP in the "uac_registration" section. (Used with supported.credentialReg.ruleTypes service property.)

Valid values are "password", "pubkey", "federated".

(Note: User Identifier Types define types of identifiers. Like a Credential Verification type is a type of CVR.)

CLS Request: Property "payloadData.uac.cvrItem.fmt" (longName: "credentialVRItem.format")

Type string. Default value: "JWK"

The format of a Credential Verification Rule being sent to the RP in the "uac_registration" section. (Used with supported.credentialReg.ruleTypes service property.)

"pubkey" values are usually of format "JWK". "password" values are usually a sting. "federated" values are ??

CLS Request: Property "payloadData.uac.cvrItem.COSE_alg" (longName: "credentialVRItem.COSE_alg")

Type integer. Default value: -7 (i.e. JWA "ES256".)

The JWK algorithm of the public key Credential Verification Rule being sent to the RP in the CVR section.

Valid "JWA_alg" values are "ES256", "RS256", "RS384", "RS512". See CLS Request.JWS.sig_alg and CLS Descriptor.JWA_alg.

CLS Request: Property "payloadData.uac.cvrItem.val" (longName: "credentialVRItem.value")

Type Object. May contain base64url encoded binary data. Required.

The value of a Credential Verification Rule being sent to the RP in the "cvrList" section of the "uac_registration". (Used with supported.credentialReg.ruleTypes service property.)

"pubkey" values are usually of format "JWK". "password" values are usually a sting. "federated" values are ??

CLS Request: Property "payloadData.uac.cvrItem.kid" (longName: "credentialVRItem.keyId")

Type string. Required.

The id of the public-key Credential Verification Rule. // The Key ID.

Must be the same as the credentialVRItem.id ("cvid").

CLS Request: Property "payloadData.uac.cvrItem.aod" (longName: "credentialVRItem.attestation_object")

Type string. Contains base64url encoded binary data. Required if serviceOp="cls/createUserLogin" or "cls/setActiveCredentials".

Base64url encoded binary data. Holds the attestation object from the LoginManager.

CLS Request: Property "payloadData.uac.cvrItem.aof" (longName: "credentialVRItem.attestation_object_format")

Type string. Default value: "WebAuthN 1.0"

Holds the attestation object format from the LoginManager.

CLS Response Detail

The Capis Login Service Response (CLS Response) is a JSON object created by the RP, and sent to the browser, in response to a CLS Request that was sent to the RP service endpoint. It consists of a single JSON object. All CLS Response objects are received and processed by the browser CLS implementation first, before any scripts on the HTML page. This is so that the browser will always know the current Login Status at the RP.

The response JSON object can contain a success code or error, etc. If the serviceOp sent to the RP was "createUserLogin" then the response from the RP will contain the new assignedUserId. (Or an error.)

The "error" property contains the error code, message, etc. A json response must only have EITHER a 'result' OR a 'error' property. A single response cannot have both.

Example CLS Response JSON object:
{
  "cls_ver":"1",
  "id": 1234567890,
  "result": {
    "svCall": "cls/login",
    "assignedUserId": "ciq:C:A:1:00000000",
    "sessionUserId": "q3jC9-h",
    "alt_user_id": "ciq:C:A:2:Gib9Ysc"
  },
  "comment_22": "The 'result' and 'error' properties cannot both exist in a single response.",
  "error": {
    "code": 1492,
    "message": "Parse error",
    "message_2": "Method not found",
    "message_3": "Parse error",
    "message_4": "Invalid request",
    "data": { "some property":"some data" }
  }
}

CLS Response - List of Properties

Special JSON properties used in the "service response" JSON object

The following properties can be used in the "service response" JSON object.

CLS Response: Property "responseData.id" (longName: "id")

Type integer. Required.

The id number of the request. The response must have the same id number as the corresponding request. The sender may use these numbers to identify the request and response.

CLS Response: Property "responseData.result" (longName: "result")

Type Object. Required if an error did not occur.

Contains the result value from the CLS Request. A response may only have ONE of "result" or "error". It may not have both.

Example CLS Response JSON object:
{
  "cls_ver":"1",
  "id": 1234567890,
  "result": {
    "svCall": "cls/login",
    /* "assignedUserId": "ciq:C:A:1:00000000", Not used with "login" */
    "sessionUserId": "q3jC9-h",
    "alt_user_id": "ciq:C:A:2:Gib9Ysc"
  }
}

CLS Response: Property "responseData.error" (longName: "error")

Type Object. Required if an error occurred.

Contains the error object resulting from the CLS Request. A response may only have ONE of "result" or "error". It may not have both.

CLS Response: Property "responseData.result.svCall" (longName: "serviceCall")

Type string. Required.

Contains the serviceOp value from the CLS Request.

CLS Response: Property "responseData.result.assignedUserId" (longName: "assignedUserId")

Type string. Required if serviceOp="cls/createUserLogin", and not using a multi-site UserId.

Sent in response to the "createUserLogin" and "changeUserId" opId.

When the opId is "createUserLogin", the browser should set the uid.timestamp_uid property. The RP will create a new assignedUserId and send it to the browser in an encrypted form. The browser should send it to the Login Manager, using LoginManager.setUserLoginDetails() in newProperties.updatedUserId. The Login Manager will decrypt the value and store it, associated with the login.

Example CLS Response JSON object:
{
  "cls_ver":"1",
  "id": 1234567890,
  "result": {
    "svCall": "cls/createUserLogin",
    "assignedUserId": "ciq:C:A:1:00000000",
    "sessionUserId": "q3jC9-h",
    "alt_user_id": "ciq:C:A:2:Gib9Ysc"
  }
}

CLS Response: Property "responseData.result.sessionUserId" (longName: "sessionUserId")

Type string. Required.

Sent by the RP in response to a "login" action. (i.e. The "login" and "createUserLogin" opId)

The encrypted UserId and the UserId session key are extra features to protect User Privacy. They both hide the real UserId from the browser. So that the user can use any browser and the UserId for all RP websites will remain secret from the browser.

The sessionUserId is a temporary value the RP creates to "stand-in" for the real UserId.

The browser must remember the sessionUserId. It must send the sessionUserId as the UserId session key value when performing most actions. Example: "cls/logout", "cls/proveUserPresence", etc. If the browser is not looged into the RP website, then the browser must send to the RP an "encrypted UserId". Example: UserId using encryption method 1

RP User Authentication Process

The RP user authentication process (login process) has the following flow:

If the RP verification page receives an HTTP POST request, and the request does not contain the special HTTP parameter (Default name is "capis_request"), then the user's browser does not support the CAPIS specification. The browser simply followed the "href" attribute of the HTML anchor, like normal, and did not add any "_auth_" parameters. In this case, the RP should redirect the user to some other login method. It can also use the default fallback identity login path. See Appendix D - Browser does not support CAPIS HTML Elements

Alternately, it may be easier for the RP verification page to detect a GET request, and redirect on that. But this can only be done if the RP is certain that all GET requests are errors (from older browsers) and all POST requests are correct. Check that the RP does not allow GET requests (in the RP Config Document), and check that the RP does not send form submissions to the same endpoint.

During the identity proof verification, the RP must check to see if it has a record for the given UserId. If it does have a record for the UserId, then the RP must retrieve all the Credential Verification Rule for the UserId, and the "Credential Verification Methods" for each CVR. Then use the methods to verify each Credential Verification Rule in the identity to the identity proof. If verification fails, then the RP generates and returns a verification error message. (Ex: "The provided identity proof is not valid. Please provide different proof in order to login.")

If RP does not recognize a UserId, then one of two (or more) error messages must be returned. In other words, if an account DOES NOT EXIST for the specified user id. To determine which error message to return, the token must still be validated. Only if the token is valid (and any UserId certificate is also valid), then the user has successfully unlocked the Locked Id. Then the user is who he claims to be, and has proven he owns the UserId. (The user trying to log in is therefore authorized to use the user id he claimed.) If the user is verified, then the return message will be the "unknown user" error message. (This should be "unregistered user". No account exists for this user.) The user should then be prompted to create an account, with the proven user id. (Ex: An account does not exist for that user. Click here to create an account.)

If the token is NOT valid, then the RP should send a generic authentication error message. This prevents unverified users being able to determine if an account exists for any un-owned UserId. The situation where the existence of an account connected to any user id can be queried by anyone, even if they do not own the user id.

Note that an RP SHOULD NOT automatically create an account for identities in response to a login CLS Request. (When a user tries to login with an identity, the identity is VERIFIED, but the RP does not have an account for that identity.) Instead, confirmation from the user is required before User Login creation. (To prevent User Login creation due to user error. If the user accidentally selected the wrong identity to log in with, etc.) See User Login creation and opId.createUserLogin.

If the signature is not valid, then an error message is displayed to the user. Note that the login process does not necessarily require the server to communicate with any other website. (This is unlike Mozilla Persona, Open ID, Facebook Connect, etc.) Only if the "authentication method" is for a third party server (an identity provider, etc.) then communication must be done with a third party. Note that the login process does not send the server (the RP) a password. The server does not store or validate passwords. It stores a public key and validates a digital signature.

========

CAPIS (and CapisLogin) Javascript implementation

The goal is that browsers will implement Capis Login natively. However, until that time, there is a javascript implementation.

  1. RP web pages must have the CapisLogin API library. (The code to be executed.)
  2. RP web pages that use "capis-trigger" HTML elements should include a script in the head. <script src="capis_library.js"></script>
  3. It hooks up all the CAPIS HTML Elements to use the activateTrigger behavior. (It calls CapisControl.activateTrigger.)
    The CAPIS Anchor and button HTML Elements call the activateTrigger when they are clicked. The CAPIS Form HTML Elements call activateTrigger when they are submitted.
  4. There must be a way for the library to access the user's RP credentials. The "UserLogins" could be stored on the user's machine, or in the browser or at a particular website. (In cookies, in localStorage, etc. How to do this?
  5. OLD. There must be a way to obtain a "proof of identity". This may involve communicating with an external website. The user's IdP. There must be a standardized way of automatically communicating with the IdP.

Step 1. Attach CapisControl.activateTrigger as a click handler to all CAPIS Anchor HTML Elements. Use CSS selector "a[rel=capis-trigger]" and "addEventListener" to add a click handler.

function connectAllAuthEnabledElements() {
  let capisLogin_api = navigator.id.capisLogin_api;
  let capisAnchorList = window.document.querySelectorAll("a[rel=capis-trigger]");
  let inputButtonList = window.document.querySelectorAll("input[rel=capis-trigger]");
  let buttonList = window.document.querySelectorAll("button[rel=capis-trigger]");
  let clickList = [];
  capisAnchorList.forEach(function (item) {clickList.push(item);})
  inputButtonList.forEach(function (item) {clickList.push(item);})
  buttonList.forEach(function (item) {clickList.push(item);})

  clickList.forEach((item)=> {
    item.addEventListener("click", function(evt){evt.preventDefault(); capisControl_api.activateTrigger(this, evt);});
  });
  let capisFormList = document.querySelectorAll("form[handling=capis-trigger]");
  capisFormList.forEach((item)=> {
    item.addEventListener("submit", function(evt){evt.preventDefault(); capisControl_api.activateTrigger(this, evt);});
  });
}
window.addEventListener("load", connectAllAuthEnabledElements);

The browser needs to treat CAPIS Anchor HTML Elements as if they had a standard capis javascript click handler.

Example Anchor:
<a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" ' onclick="function(evt){capisControl_api.activateTrigger(this, evt)}">Login</a>

CLS Remote Usage. Calling the CapisLogin API functions from non-RP web pages

It can be beneficial for a browser to store links directly to RP RP Config Documents. Browsers are encouraged to store "cls/login" links. This way, the user does not have to load the RP website in order to look for a "cls/setActiveCredentials" link on the RP website. The "capisDocUri" in the login link is generally the same destination as a "cls/setActiveCredentials" link. (As part of its "password manager", the browser remembers all links where the user logged in via the "cls/login" serviceOp.) Therefore, the browser or password manager can display an option screen to the user, and it can contain generated links to RPs to change the user's public key at that RP.

<a href="..." rel="capis-trigger" capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>

Form Signing

An RP can request that a form be cryptographically signed by the user when it is submitted. This may help prove that the user made the submission, or agreed to the terms in the form, etc. An RP does this by setting the "serviceOp" property to be "cls/signData". (Note that the "serviceOp" property referred to here is not the "action" attribute of the form. Instead, it is one of the Trigger Configuration Options inside the "capis-config" attribute.)

Example Form:
<form action="some_uri" handling="capis-trigger" capis-config=' "serviceOp":"cls/signData", "redirectUri":"/some/path/page.html" '>

"Form-signing" can be used for:

Form snapshot

A signed form must contain much more data than a regular form submission. This data is contained in a "form snapshot". It is a JSON representation of the form.

How it works

The use of the "signData" opId (along with the handling="capis-trigger" attribute) will cause the CapisControl.activateTrigger(formElement) function to be executed instead of the regular browser behavior when the submit button is pressed. This new function does the same as the regular behavior, validates the form as usual, fires the same events, etc. but as a last step, it causes the CapisLogin.performUserAuth("signData", callOptions) function to be executed, instead of submitting the form.

The CapisLogin.performUserAuth("signData", callOptions) function causes a "form signature" pop-up dialog to be displayed to the user. (Instead of submitting the form.) The pop-up dialog shows a pull-down menu for the user to select which certificate (which UserLogin) to use to sign the form. There is also an option to create or import a UserLogin. After the UserLogin is selected, the CapisControl.createFormSnapshot(formElement, UserId) function is called. And that creates a form signature and adds it as "proof" to the CLS Request JSON object.

When the submit button is pressed, all regular javascript code runs (such as a validator, and event listeners). The validator, etc, may stop the form submission before the performUserAuth("signData", callOptions) function is called.

More details:

The activateTrigger function gets the serviceOp property. It then calls CapisControl.invokeServiceAction.

First, the invokeServiceAction function detects that the htmlElement is a form. Then it calls the regular "onsubmit" javascript code. (a validator, etc.) If the regular code returns a false or otherwise stops the form submission, then invokeServiceAction stops execution. Second, if the form is still to be submitted, then the invokeServiceAction function checks if the opId is "signData". If it is, then the form signing path is taken. Third, a dialog is presented to the user asking which UserLogin (and key) they want to use to sign the form. Fourth, the invokeServiceAction function creates a JWT, that has all the data in the form copied to the JWT payload section. Fifth, it signs the JWT with the user's private key, and adds the JWT to the CLS Request JSON object, as an additional property.

An example HTML form:


What is your gender? : :
What kind of car do you want?

<form action="/_capis/fallback/signForm.html" handling="capis-trigger" capis-config=' "serviceOp":"cls/signData", "redirectUri":"/some/path/formConfirm.php" '> <input type="text" name="firstname" placeholder="Enter your first name"><br/> <input type="text" name="lastname" placeholder="Enter your last name"><br/> What is your gender? <label for="i_male">Male</label>: <input type="radio" id="i_male" name="gender" value="male"> <label for="i_female">Female</label>: <input type="radio" id="i_female" name="gender" value="female"><br/> What kind of car do you want?<br/> <select multiple name="carmake"> <option value="volvo">Volvo</option> <option value="toyota">Toyota</option> <option value="ford">Ford</option> </select><br/> <input type="hidden" name="today_date" value="2018-01-12"> <input type="submit" value="Submit"> </form>
{
  "id": "service_1",
  "protocol": "capis_login_service",
  "endpoints": [
    { "id":"endpoint_1", "sUri":"/_capis/cls/serviceCall", "request_format":"JWS" }
  ],
  "userIdRules": {
    "userIdTypes": ["single_site_userId", "ciq:C:B1:9:ri"],
    "createMethods": ["assigned_ulc", "claim_ms_ulc"]
  },
  "supported": {
    "credentialReg": {
      "passwordTypes": [{"name":"password_s1", "maxLength":14, "storageQuantity":"1"}],
      "publicKeyTypes": [{"name":"pubkey_s1", "JWA_alg":"ES256", "storageQuantity":"1"}]
    },
    "userAuthScheme": {"methods":["stored_cred", "only_MSUID"]},
    "supported.uic.csvm": ["basic1", "basic2"]
  },
  "requirement_section": {}
}
The HTTP values:
firstname=Mickey
lastname=Mouse
gender=male
carmake=toyota,volvo
Example CLS Request JSON object:
let payload_unencoded = { "request_spec": "capis 0.1" "protocolId": "cls", "reqOp": "signData", "sub": "cls/signData", "iat": 1503971280, // issuedAt timestamp "exp": 1533064012, // expiresAt timestamp "aud": "RP_example.com", // the audience "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", // nonce value "nit": 1533064012, // nonceIssueTime "uid": { "raw": "ciq:C:F1:1:1234567890:ACMA_org", // The ciq UserId "usk": "q3jC9-h" }, "user_auth_method": "only_MSUID", "redirectUri": "/some/path/page.html", "useCount": 42,
// user_id_certificate_chain (Available when not using the "stored_cred" uauth_method.) "uic_chain": [ {"uic.format":"JWS", "uic.csvm":"YY", "ucv": { "payload":"82h7vb...", "signatures": [...] }} ],
// crProofSection. "crProofSection": { "uid": { "raw2": "ciq:C:B1:2:xxxxxxxx", // The ciq UserId }, "uapCounter": 42, "cpl": [ { "cpid": "cd2", "cpt": "pubkey", "cpf": "TBD-CPF", // "credentialProofItem.format": "TBD-CPF" (not necessary. The default is "TBD-CPF".) "cpv": "mmmm" // base64url encoded JWT or signature. } ] }, "form_details": { "iss": "ciq:C:B1:2:K8h3_TfXr6ZtLq7d1m8k", // The Backer doing the signing. formSnapshot: [ // The form contents. {"n":"firstname", "t":text", "v":"Mickey"}, {"n":"lastname", "t":"text", "v":"Mouse"}, {"n":"gender", "t":"radio", "v":"male", "o":[{"l":"Male","v":"male","s":true},{"l":"Female","v":"female"}]}, {"n":"vehicle", "t":"checkbox", "v":[], "o":[{"l":"I have a bike","v":"Bike"},{"l":"I have a car","v":"Car"}]}, {"n":"carmake", "t":"select-multiple", "v":["toyota","volvo"], "o":[{"l":"Toyota","v":"toyota","s":true}, {"l":"Volvo","v":"volvo","s":true},{"l":"Audi","v":"audi"}]} ] }, /* uac_registration. Not required for "form-sign" serviceOp. "uac": { "backup_credentials": [ { "cvid": "cd-3", "typ": "pubkey", "fmt": "JWK", "COSE_alg": -7, "val": { ... } } ], "cvrList": [] } */ }; let CLS Request = { "JWS": { "payload": BASE64URL(UTF8(payload_unencoded)), "signatures": [{ "protected": "eyJhbGciOiJFUzI1NiJ9", // protected_header = {"alg":"ES256", "sct":192} "header": { "kid": "cd1", "kid2": "e9bc097a-ce51-4036-9562-d2ade882db0d" // "kid": "userIdPK" // "userIdPK" means the public key is in "uid". }, "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga" }] } }

The "UserId certificate" JWT. header and claims: (uic_chain[0])

let payload_unencoded = { "sub2": "cls/certificate", "iss": "id_registrar.example.com", // The Backer "iat": 1503971280, "exp": 1533064012, "sub": "ciq:C:F1:1:1234567890:ACMA_org", // The ciq UserId. "uid": { "raw": "ciq:C:F1:1:1234567890:ACMA_org", // The ciq UserId. "usk": "q3jC9-h" }, "cert_pubKeyList": [ { "kty": "RSA", "kid": "f85762a7f52c8346", "alg": "RS256", "n" : "4b9e34...", "e" : "93bc32..." } ] } let jws_certificate = { "payload": BASE64URL(UTF8(payload_unencoded)), "signatures": [ { "protected": "eyJhbGciOiJSUzI1NiJ9", // protected_header = {"alg":"RS256", "sct":192} "header": { "alg": "RS256", "kid": "bf4a76332a6c8370f48", // "kid" is REQUIRED "csvm": "RDAC" // How to get the sig verification key from the issuer. // "csvm": "OIDCD" // Get the sig verification key from the issuer via "OIDCD", etc. // "csvm": "idr_keystore" // Get the sig verification key from an "Backer keystore". }, "signature": "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4Ga" }] }

The JWT MUST have an issue date, and an issuer string that contains the UserLogin. That is, the required fields include the "kid" value in the header, and both an "iat" and "iss" claim values. When validating the form, the issuer string is extracted, and used to look up the sig verification key set for that issuer. The "kid" specifies which key was used. (Note that the key used may not belong to the RP. The RP may need to retrieve the list of keys from an internet address.)

Form Snapshot

A form snapshot is a JSON representation of the form. The HTML form is converted into JSON, and most of the form fields and attributes are retained.

A form snapshot must contain much more data than a regular HTTP form submission. A form snapshot is about proving what data a user provided, and thus it is necessary to document the questions on the form, and what options were available for each of them. An HTTP form submission is not sufficient, as it only contains the values that were sent to the server. It doesn't contain the labels, options or even the field types (text, radio button, etc). Furthermore, there is no distinction between the values the user provided, and values from "hidden" input elements. Without this distinction, it would be possible for form authors to add hidden form fields and make it seem that a user agreed to something they were not aware of.

A form snapshot converts each input element in a form into a JSON object. Each converted input element will include the name, type, value, label, and the options available. The options will include the label, value and a marker for if the option is selected. Each option can have its own label.

See CapisControl.createFormSnapshot(formElement).

CAPIS API Function: CapisControl.createFormSnapshot(formElement)

Return type: Object.

Converts an HTML form into a JSON object. Retains most of the form fields, attributes, labels and options.

Function info: (parameter list, return value, etc.)
  • @param {Object} formElement. The HTML form element to extract the data from.
  • @return {Object} formSnapshot. Returns a javascript object.
  • @property {string} name.
  • @property {integer} creationDate. Date of creation. Unix timeestamp in milliseconds.
  • @property {Array} elementList.
  • @example_object The array items, they contain name "n", type "t", value "v", option_list "o".

This function goes through the form, and converts each input element into a JSON object. Each converted input element will include the name, type, value, label, and the options available. The options will include the label, value and a marker for if the option is selected. Each option can have its own label. (The options are limited to 50 for select fields).

A form snapshot is necessary because the regular HTTP form submission does not retain the questions on the form. It doesn't contain the labels, options or even the field types (text, radio button, etc). Without that data, it is hard to verify what questions the user was answering. See Form Snapshot.

See Form signing.

Details:

The snapshot:

The form snapshot contains a lot more data than a standard form submission. It contains:
Example HTML form:
<form action="/_capis/fallback/signForm.html" handling="capis-trigger" capis-config=' "serviceOp":"cls/signData", "redirectUri":"/some/path/formConfirm.php" '> <input type="text" name="firstname" placeholder="Enter your first name"><br/> <input type="text" name="lastname" placeholder="Enter your last name"><br/> <input type="text" id="i_nickname" name="nickname"><label for="i_nickname">What you like to be called.</label><br/> What is your gender? <label for="i_male">Male</label>: <input type="radio" id="i_male" name="gender" value="male"> <label for="i_female">Female</label>: <input type="radio" id="i_female" name="gender" value="female"><br/> What kind of vehicles do you have?<br/> <input type="checkbox" id="i_bike" name="vehicle" value="Bike" checked> <label for="i_bike">I have a bike</label><br/> <input type="checkbox" id="i_car" name="vehicle" value="Car" checked> <label for="i_car">I have a car</label><br/> <input type="checkbox" id="i_boat" name="vehicle" value="Boat"> <label for="i_boat">I have a boat</label><br/> <select multiple name="carmake"> <option value="volvo">Volvo</option> <option value="toyota">Toyota</option> <option value="ford">Ford</option> </select><br/> <input type="hidden" name="today_date" value="2018-01-12"> <input type="submit" value="Submit"> </form>
// createFormSnapshot example output.
formSnapshot: {
  "creationDate": 1555876543210,
  "elementList": [ // The form contents.
    {"n":"firstname", "t":text", "v":"Mickey"},
    {"n":"lastname", "t":"text", "v":"Mouse"},
    {"n":"nickname", "t":"text", "v":"Big Ears", "l":"What you like to be called."},
    {"n":"gender", "t":"radio", "v":"male", "o":[{"l":"Male","v":"male","s":true},{"l":"Female","v":"female"}]},
    {"n": "vehicle", "t": "checkbox", "v":[],
        "o":[{"l":"I have a bike","v":"Bike"},{"l":"I have a car","v":"Car"},{"l":"I have a boat","v":"Boat"}]},
    {"n": "carmake", "t": "select-multiple", "v":["toyota","volvo"],
      "o":[{"l":"Toyota","v":"toyota","s":true}, {"l":"Volvo","v":"volvo","s":true},{"l":"Ford","v":"ford"}]}
    {"n":"today_date", "t":"hidden", "v":"2018-01-12"},
  ]
}

In JSON, names and values cannot contain double quotes. So, both the names and values of the form items will need to have any double quotes encoded. (Should use json encoding, backspace, '\"', not html "&quot;")

Example javascript code for creating a Javascript object with all the form names and values.
// example implementation
/**
 * Extracts structure and user data from a form as an array of data objects.
 * Objects include name, value, type, option_list and option labels.
 * Important: checkboxes and radio buttons with the same name are combined.
 * Each individual radio button or checkbox is one option for the shared name.
 * Single select items (radio, select-one) will have a value of null if nothing is selected.
 * Multi-select items will have a value of the empty array if nothing is selected.
 * Also, the array of selected options ("so"), is an attempt to minimize the length of the option list.
 * @return {Object} formSnapshot. Returns a javascript object.
 * @property {string} name.
 * @property {integer} creationDate.
 * @property {Array} elementList.
 * @example_object The array items, they contain name "n", type "t", value "v", option_list "o".
 */
function createFormSnapshot(theForm) {
  if (theForm === undefined || theForm.nodeName !== "FORM") {
    throw new Error("Cannot create a form snapshot. No form provided.");
  }
  let formData = {}; // The data to be signed.
  formData.creationDate = new Date().getTime();
  let itemList = []; // The list of elements
  let data_names = {};
  let elem;
  let formLen = theForm.elements.length;
  for(let i = 0; i < formLen; i++) {
    elem = theForm.elements[i];
    switch (elem.type) {
    case "hidden":
    {
        let item = {};
        item.n = elem.name;
        item.t = elem.type;
        item.v = elem.value;
        // item.l = getLabelFor(theForm, elem.id);
        itemList.push(item);
    }
        break;
    // These types do not have a "name". submit, reset, button, image
    case "submit":
    case "reset":
    case "button":
    case "image":
        break;
    // Do not include passwords in the itemList.
    case "password":
    // case "file":
        break;
    case "select-multiple":
    {
        let item = {};
        let options = [];
        item.n = elem.name;
        item.t = elem.type;
        item.v = [];
        item.l = getLabelFor(theForm, elem.id);
        item.o = options;
        itemList.push(item);
        item.so = []; // Array of only the selected options.
        let so = item.so;
        for(let k = 0; k < elem.length; k++) {
          let op = {};
          op.l = elem.options[k].text;
          op.v = elem.options[k].value;
          options.push(op);
          if(elem.options[k].selected) {
            op.s = true; // option is selected.
            item.v.push(elem.options[k].value);
            so.push(op);
          }
        }
    }
        break;
    case "select-one":
    {
        let item = {};
        let options = [];
        item.n = elem.name;
        item.t = elem.type;
        item.v = null;
        if (elem.selectedIndex != -1) { item.v = elem.options[elem.selectedIndex].value; }
        item.l = getLabelFor(theForm, elem.id);
        item.o = options;
        itemList.push(item);
        for(let k = 0; k < elem.length; k++) {
          let op = {};
          op.l = elem.options[k].text;
          op.v = elem.options[k].value;
          options.push(op);
          if (elem.options[k].selected) {
            op.s = true; // option is selected.
          }
        }
    }
        break;
    case "radio":
    {
        let item;
        if (elem.name in data_names) {
          item = data_names[elem.name];
        } else {
          item = {};
          item.n = elem.name;
          item.t = elem.type;
          item.v = null;
          item.o = []; // options
          itemList.push(item);
          data_names[elem.name] = item;
        }
        let options = item.o;
        let op = {};
        op.l = getLabelFor(theForm, elem.id);
        op.v = elem.value;
        options.push(op);
        if(elem.checked) {
          op.s = true; // option is selected.
          item.v = elem.value;
        }
    }
        break;
    case "checkbox":
    {
        let item;
        if (elem.name in data_names) {
          item = data_names[elem.name];
        } else {
          item = {};
          item.n = elem.name;
          item.t = elem.type;
          item.v = [];
          item.o = []; // options
          item.so = []; // Array of only the selected options.
          itemList.push(item);
          data_names[elem.name] = item;
        }
        let options = item.o;
        let op = {};
        op.l = getLabelFor(theForm, elem.id);
        op.v = elem.value;
        options.push(op);
        if(elem.checked) {
          op.s = true; // option is selected.
          item.v.push(elem.value);
          let so = item.so;
          so.push(op);
        }
    }
        break;
    // text, textarea, etc.
    default:
    {
        let item = {};
        item.n = elem.name;
        item.t = elem.type;
        item.v = elem.value
        item.l = getLabelFor(theForm, elem.id);
        itemList.push(item);
    }
    }
  }
  formData.elementList = itemList;
  return formData;
}
function getLabelFor(theForm, theId) {
  let label = "";
  let html_labels = theForm.querySelectorAll("label[for='" + theId + "']");
  for( let index=0; index < html_labels.length; index++ ) {
    // Probably need some check in here to ensure the label is visible.
    label += html_labels[index].textContent;
  }
  return label;
}
========

API data types

string // Data must be a string.
integer // Data MUST be an integer. (Not a float)
number // Data may be an integer or a float.
boolean
Object
Array

API Types Type: JSON Property List (JSON-PL)

Type JSON Property List
Used by HTML ATTRIBUTE
Contains a JSON-style list of name-value pairs. It is standard JSON, except that it allows property names and string values to be alternately enclosed in single quotes, instead of requiring double quotes. This is for convenience, because HTML attribute values can be double quoted, and that interferes with standard JSON quoting. The entire attribute value is treated as a single JSON object.
Example ABBA:
<a href="/_capis/fallback/login.html" rel="capis-trigger" capis-config=" 'serviceOp':'cls/login', 'redirectUri':'/some/path/page.html' ">Login</a>

API Library

Optional Javascript Library

A set of API functions for the browser to call in order to perform the behavior required of "auth" elements. These API functions are exposed as Javascript functions.

// Example use of a "service descriptor"
let siteInfo = {
  "documentId": "4857a8d28f6c",
  "rpInfo": {
    "displayName": "123done",
    "smallIcon": "/images/logo.png"
  },
  "serviceList": [...]
};
let service_info = { "id": "service_1",
  "protocol": "capis_login_service",
  "endpoints": [
    { "id":"endpoint_1", "sUri":"/_capis/cls/serviceCall", "request_format":"JWS" }
  ],
  "userIdRules": {
    "userIdTypes": ["single_site_userId", "ciq:C:B1:9:ri"]
    // "createMethods": ["assigned_ulc", "claim_ms_ulc"]
  },
  "supported": {
    "credentialReg": {
      "passwordTypes": [{"name":"password_s1", "maxLength":14, "storageQuantity":"1"}],
      "publicKeyTypes": [{"name":"pubkey_s1", "JWA_alg":"ES256", "storageQuantity":"1"}]
    },
    "userAuthScheme": {"methods":["stored_cred", "only_MSUID"]},
    "supported.uic.csvm": ["basic1", "basic2"]
  }
}

The CapisControl.activateTrigger is the top level and accept a CAPIS HTML Element. Internally, they call CapisControl.invokeServiceAction(serviceOp, callOptions).

Note that "many of" these functions have a "context" of the current browser tab.

All the "capisDocUri" values must start with a slash. (Also "smallIcon" values too.) They CANNOT contain a domain name. It's a security risk. This is because the functions can be called directly from javascript running in a browser tab. A tab should not be able to log into or out of a different site. (Cross site scripting attack.)

API Table Of Contents

API Class: CapisControl

Global API Object: capisControl_api

API Class: CapisLogin

Global API Object: capisLogin_api

Level 1 Javascript API functions.

API Class: LoginManager

The LoginManager functions are called from LoginDirector functions.
The LoginManager functions that accept the "rpClientData" argument are Authenticator functions. (And findUserLogins is also a required Authenticator function.) The purpose of rpClientData is to be included in a signature, created by the Authenticator, and returned to the RP. This lets the RP know that the Authenticator received the correct data. For example, The RP can choose to use a parent domainName. The RP needs proof that the Authenticator knew that when it created the signature. The rpClientData is used when a response from the Authenticator is delivered to the RP. The rpClientData is used (1) when creating credential signatures, and (2) When CHANGING active credentials (3) when creating a User Login. (Note: creating credential sources does NOT require an rpClientData.) The credential signatures and attestation signature are signed over the rpClientData hash.

API Class: LoginDirector

Low level functions, internal to the browser implementation. These are suggestions only. They are not public, and could be implemented completely differently. The first group is called by the CapisLogin functions.
======== Private Key APIs. ========
  • authsecure.generateKeyPair() -- Generates a key pair. Stores private key securely. -- Also generates an "id" for the key pair. Records the keys internally. Returns only the public key.
  • authsecure.createIdentitySignature(); -- Creates a JWT signed by the userId private key.
  • LoginManager.buildProofForRp(header, payload, privateKey);

CAPIS API Function: CapisControl.activateTrigger(htmlElement)

Return type: void. (nothing)

This is the "CAPIS click handler" function.

Called by the browser when the user clicks an RP Service Trigger HTML Element. (Such as a CAPIS Anchor HTML element with rel="capis-trigger" attribute.)

Internal steps:

This handler registers an internal function as a failure callback to receive error and failure notifications from the CapisControl.invokeServiceAction function. If "CapisControl.invokeServiceAction" encounters an error, or cannot complete correctly for any reason, then the failure callback is called. That will return control to this handler. It may then decide to display an error message to the user (as a popup or dialog box, etc.), or pass the error on to the browser.

For example: if a login was started, but the user cancels it. or the user supplied the wrong password to the IDP, etc. etc.

Extracts all the authentication configuration options from the anchor element (inside the "capis-config" attribute). For example, this includes: "serviceOp", "challenge", etc.

Example ClientConfig Options HTML:
// arguments
<link href="/some/path/capis_config.json" rel="capis-base"
 capis-config=' "nonceIssueTime": 1533064012,
  "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
  "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
  "mediation": "required"}] '/>
...
<a href="/some/capislogin/fallback/login.html" rel="capis-trigger"
 capis-config=' "serviceOp":"cls/login", "redirectUri":"/some/path/page.html" '>Login</a>
Example implementation code.
// example implementation
function activateTrigger(htmlElement, event) {
  let callOptions = GCA_createCallOptions(htmlElement);
  let serviceOp = callOptions.serviceOp;
  return capisControl_api.invokeServiceAction(serviceOp, callOptions)
  .then( action_response => {
    // console.log("CapisControl.activateTrigger: resolved. response=" + JSON.stringify(action_response));
    return action_response;
  }).catch(error => {
    // console.log("Error in CapisControl.activateTrigger. " + error.message);
    return Promise.reject(error);
  });
}

function GCA_createCallOptions(htmlElement) {
  var extractionResult = capisControl_api.extractConfigOptionsFromElement(htmlElement);
  var callOptions = extractionResult.jsonDataObject;
  const internalDataPropName = "capisHtmlSourceInfo";
  callOptions[internalDataPropName] = extractionResult.otherInfo;
  if (htmlElement.nodeName == "FORM") {
    let formElement = htmlElement;
    let svActionFieldId = callOptions["setServiceActionByFieldId"];
    if (svActionFieldId !== undefined) {
      // Create a special query selector. That fixes the colon and backslash characters.
      let fieldId_qs = svActionFieldId.replace(/\\/g, "\\\\"); // escape the backslash char.
      fieldId_qs = fieldId_qs.replace(/:/g, "\\:"); // escape the colon char.
      let fieldElement = formElement.querySelector("#" + fieldId_qs);
      let fieldValue = (fieldElement != null)? fieldElement.value : undefined;
      if (fieldValue !== undefined && fieldValue != "") {
        callOptions.serviceOp = fieldValue;
      }
    }
    let setUserIdRuleCfgByFieldId = callOptions["setUserIdRuleCfgByFieldId"];
    if (setUserIdRuleCfgByFieldId !== undefined) {
      let fieldId_qs = setUserIdRuleCfgByFieldId;
      fieldId_qs = fieldId_qs.replace(/:/g, "\\:"); // escape the colon char.
      // let link_element = window.document.head.querySelector("link[rel=capis-base]");
      // let fieldElement = formElement.querySelector("input[id=" + fieldId_qs + "]");
      let fieldElement = formElement.querySelector("#" + fieldId_qs);
      let fieldValue = (fieldElement != null)? fieldElement.value : undefined;
      if (fieldValue !== undefined && fieldValue != "") {
        callOptions.userIdRuleCfg = JSON.parse(fieldValue);
      }
    }
  }
  return callOptions;
}

CAPIS API Function: CapisControl.invokeServiceAction(serviceOp, callOptions)

Return type: Promise(Object).

Performs the operation specified in the serviceOp parameter.

Function info: (parameter list, return value, etc.)
  • @param {string} serviceOp - The requested operation to be performed. Example: "cls/login"
  • @param {Object} CapisAPI.callOptions. The configuration options for the RP service call.
  • @return {Promise(Object)} serviceCallPromise. The id (or promise) of the service call.
Internal steps:
  • Determines what serviceOp to perform ("cls/login", "cls/logout", etc.) from reading the serviceOp property.
  • Returns the Promise created from calling the serviceOp function.

This function returns a Promise. If for any reason this function cannot complete correctly, then the promise's failure callback will be executed. For example, if the user cancels the login attempt, or the user supplied the wrong password.

The promise's failure callback is NOT called if the function completes correctly. For example, if the POST is sent to the website, the failure callback will never be called. Even if the website rejects the login or has some other error. In this example, if the website has an error, it can redirect the browser to a web page detailing the error.

Example implementation code.
// example implementation
function invokeServiceAction(serviceOp, callOptions) {
  if (callOptions === undefined) { callOptions = {}; }
  if (serviceOp === undefined) { serviceOp = "cls/login"; }
  // let serviceOp2 = callOptions.serviceOp;
  let capisInternalUse = {};
  const capis_login_protocol_abbr = "cls";
  let protocol_abbr;
  let opId; // serviceMethod
  let index = serviceOp.indexOf("/");
  if (index != -1) {
    protocol_abbr = serviceOp.substring(0, index);
    opId = serviceOp.substring(index + 1);
  } else {
    protocol_abbr = "";
    opId = "";
  }
  capisInternalUse.orig_protocol_abbr = protocol_abbr;
  capisInternalUse.orig_comboAction = serviceOp;
  callOptions.capisInternalUse = capisInternalUse;
  return this.ensureClientConfig()
  .then( clientConfig => {
    // let sapId = clientConfig.activeSapId;
    if (protocol_abbr == capis_login_protocol_abbr) {
      return capisLogin_api.performOp(opId, callOptions);
      // Note: "performOp" will call CapisLogin.performUserAuth.
    } else {
      return Promise.reject("Unknown serviceOp prefix. Not 'ua'. serviceOp=" + serviceOp);
    }
  }).then( prHandlerResponse => {
    se9_debug.log("CapisControl.invokeServiceAction: resolved. response=" + JSON.stringify(prHandlerResponse));
    // window.location.reload();
    let action_response = prHandlerResponse;
    return action_response;
  }).catch( error => {
    let msg = "Error in CapisControl.invokeServiceAction. error=" + error;
    console.log(msg);
    alert(msg); // alert("Error in CapisControl.invokeServiceAction. error=" + error.message);
    return Promise.reject(error);
  });
}

CAPIS API Function: CapisControl.evaluateServiceResponse(svRequestId, serviceResponse)

Return type: Promise(Object).

Evaluates the service response.

Function info: (parameter list, return value, etc.)
  • @param {string} svRequestId. The ID of the request sent to an RP service. Ex: "264"
  • @property {Object} svReqContext. The service request context. (of the client.) Ex: The HTML page that made the call.
  • @param {Object} serviceResponse. The response sent from the RP service.
  • @return {Promise(Object)} eval_response. The response object.
  • @property {Object} serviceResponse. The serviceResponse object that was passed in as an argument.
Example implementation code.
// example implementation
function evaluateServiceResponse(svRequestId, serviceResponse) {
  let protocol_id = GCA_getServiceProtocolForRequest(svRequestId);
  if (protocol_id == "cls") {
    return capisLogin_api.evaluateServiceResponse(svRequestId, serviceResponse);
  } else {
    throw new Error("Received an invalid service response. svRequestId=" + svRequestId);
  }
}

CAPIS API Function: CapisControl.extractConfigOptionsFromElement(htmlElement)

Return type: Object

Reads the "capis-config" attribute of the htmlElement and converts it into a JSON object. It also extracts some attributes of the element (i.e. "href") and adds them to the extractionResult as "otherInfo". The extractionResult "jsonDataObject" property contains the extracted contexts of the "capis-config" attribute.

Function info: (parameter list, return value, etc.)
  • @param {Object} htmlElement. The HTML element to extract the options from.
  • @return {Object} extractionResult. The extracted result, including attributes, etc.
  • @property {Object} jsonDataObject. The extracted options from the "config options".
  • @property {string} jsonDataObject.challenge. The challenge value.
  • @property {string} jsonDataObject.serviceOp - The requested operation. Ex: "cls/login"
  • @property {Object} otherInfo. Other stuff, including element attributes, etc.
  • @example_object jsonDataObject = { name-value pairs read from the "capis-config" attribute }
Example use:
<link href="/_capis/capis_config.json" rel="capis-base" capis-config=' "nonceIssueTime": 1533064012, "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK", "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"}, "mediation": "required"}], "capisDocUri": "https://RP_example.com/some/path/capis_config.json" '/> ... <a href="/_capis/fallback/createUserLogin.html" rel="capis-trigger" capis-config=' "serviceOp": "cls/createUserLogin", "userIdRuleCfg": {"genMethods": ["st1", "ct1"], "rawUserId": "ciq:C:A:1:1234567890"}, "redirectUri": "/some/path/page.html" '>Sign Up</a> ... <form action="/_capis/fallback/login.html" handling="capis-trigger" capis-config=' "serviceOp": "cls/login", "redirectUri": "/some/path/page.html" '> <input type="text" name="username" value="" placeholder="Enter a username" /> </form>
// arguments
let extractionResult_2 = capisControl_api.extractConfigOptionsFromElement(htmlElement);
// example output
let extractionResult_1 = {
  "jsonDataObject": {
    "nonceIssueTime": 1533064012,
    "challenge": "8fK2BzE9MQ2phX6RLu1VzD4F0wgWJ3In8dKNeGo9YdK",
    "serviceList": [{"protocol":"cls", "endpoint": {"sUri":"/_capis/cls/serviceCall.json"},
    "mediation": "required"}]
  },
  "otherInfo": {
    "sourceHtmlElement": htmlElement // Reference to the original htmlElement
  }
};
let extractionResult_2 = {
  "jsonDataObject": {
    "serviceOp": "cls/createUserLogin",
    "userIdRuleCfg": {"genMethods": ["st1", "ct1"], "rawUserId": "ciq:C:A:1:1234567890"},
    "redirectUri": "/some/path/page.html"
  },
  "otherInfo": {
    "sourceHtmlElement": htmlElement // Reference to the original htmlElement
  }
};
Example implementation code.
// example implementation
function extractConfigOptionsFromElement(htmlElement) {
  if (htmlElement === undefined) return undefined;
  var extractionResult = {};
  var attributeSet = {};
  var internalUse = {};
  internalUse.sourceHtmlElement = htmlElement;
  internalUse.attributeSet = attributeSet;
  const han_capis_config = "capis-config";
  let config_text;
  if (htmlElement.hasAttribute(han_capis_config)) {
    config_text = htmlElement.getAttribute(han_capis_config);
  } else if (htmlElement.hasAttribute("data-" + han_capis_config)) {
    config_text = htmlElement.getAttribute("data-" + han_capis_config);
  } else {
    // Nothing to extract? Error?
    config_text = "";
  }
  // Note: config_text is very close to JSON. (Can have single quoted names and strings.)
  // let cfg_JSON_text = convertConfigTextToJSON(config_text);
  let configObj = parseConfigText_local(config_text);
  // Special case for "CAPIS Anchor HTML Element". Extract the "href" attribute.
  if (htmlElement.nodeName == "A") {
    internalUse.elementTypeName = "anchor";
    if (htmlElement.hasAttribute("href")) {
      attributeSet["href"] = htmlElement.getAttribute("href");
      internalUse["unsupported-anchor-href"] = htmlElement.getAttribute("href");
    }
  }
  // Special case for "CAPIS Form HTML Element". Extract the form's "action" attribute.
  if (htmlElement.nodeName == "FORM") {
    internalUse.elementTypeName = "form";
    if (htmlElement.hasAttribute("action")) {
      attributeSet["action"] = htmlElement.getAttribute("action");
    }
  }
  // Special case for "CAPIS Link HTML Element". Extract the "href" attribute.
  if (htmlElement.nodeName == "LINK") {
    internalUse.elementTypeName = "link";
    if (htmlElement.hasAttribute("href")) {
      attributeSet["href"] = htmlElement.getAttribute("href");
      extractionResult["capisDocUri"] = htmlElement.getAttribute("href");
    }
  }
  extractionResult.jsonDataObject = configObj;
  extractionResult.attr = attributeSet;
  extractionResult.otherInfo = internalUse;
  return extractionResult;
}

CAPIS API Function: CapisControl.ensureClientConfig()

Return type: Promise(Object) page_config_repository.

Ensures the CapisControl has been initialized, then returns the ClientConfig repository. This will run the CapisControl initialization, if it has not already been performed. The initialization loads the information for the page. This includes the ClientConfig options, CAPIS document, sapId, etc. For example, it extracts the ClientConfig options from the CAPIS Link HTML Element in the page. Retrieves the CAPIS document. Gets the sapId from the CAPIS document.

Fetches the "RP Config Document" from the RP.

This function finds the CAPIS Link HTML Element in the current HTML page head. Extracts the Client Configuration Options from it. (i.e. ClientConfig options) Figures out the URI of the "RP Config Document" to use. Fetches the "RP Config Document" from the RP. Returns a new options object.

As a final step, this function stores a copy of the resolved options and service descriptor so that it is available for future use.

The configuration descriptor details the authentication abilities that the RP authentication service has.

The defaultValues.capisDocUri of the RP Config Document is a "well-known" URI. (Example: "RP_example.com/.well-known/capis_config.json".)

The capisDocUri option overrides the default CAPIS document location. The protocolHandlerList property overrides the default protocolHandlerList in the RP Config Document.

CAPIS API Function: CapisControl.getClientConfig()

Return type: Object. Returns undefined if the CapisControl has not been initialized.

Gets a copy of the active values (i.e. stored values) for the current page. The CAPIS document, sapId, ClientConfig options. The user may need to call ensureClientConfig() before calling this function. Will return undefined if the CapisControl has not been initialized.

CAPIS API Function: CapisControl.getServiceConfig(protocol_id)

Return type: Object. Returns undefined if the CapisControl has not been initialized.

Gets the "Service Config" from the Config Repo. This primarily includes the set of Service Descriptor definitions. (Note, this gets BOTH the Service Descriptors from the HTML page, and from the rpConfigDoc.) The service descriptor describes the service requirements, etc... The user may need to call ensureClientConfig() before calling this function. Will return undefined if the CapisControl has not been initialized.

CAPIS API Function: CapisControl.addEventListener(event_name, callback, options)

Return type: Object. {failureReason: "alreadyExists"}

Details here.

CAPIS API Function: CapisControl.removeEventListener(event_name, callback, options)

Return type: Object. {removeCount: 1}

Details here.

CAPIS API Function: LoginManager.getBadgeList()

Return type: Promise(Object).

Gets the list of all the Badge in the LoginManager.

Function info: (parameter list, return value, etc.)
  • @return {Promise(Object)} badgeList_response. The response object.
  • The response object can contain an "error" property instead of result data.
  • @property {Object} error. The error object.
  • @property {Array} badgeList. The list of the Badge info.
  • @property {string} item.id - The id of the Badge. Example: "bdg_2"
  • @property {string} item.name - The name of the Badge. Example: "John's Work"

CAPIS API Function: LoginManager.createBadge(badgeInfo)

Return type: Promise(Object).

Creates a new Badge with the specified properties. (i.e. The badge name.)

Function info: (parameter list, return value, etc.)
  • @param {Object} badgeInfo. The collection of badge properties.
  • @property {string} name. The name to give to the badge.
  • @return {Promise(Object)} badge_info. The response object.
  • The response object can contain an "error" property instead of result data.
  • @property {Object} error. The error object.
  • @property {string} badgeId. The id of the Badge. Example: "bdg_2"
  • @property {number} selectionGrade. The priority (weight) of the Badge.

CAPIS API Function: LoginManager.setBadgeDetails(badgeId, badgeInfo)

Return type: Promise(Object).

Sets the info of the Badge. Primarily, this sets the name of the Badge.

Function info: (parameter list, return value, etc.)
  • @param {string} badgeId. The badge id.
  • @param {Object} badgeInfo. The collection of badge properties.
  • @property {string} name. The new badge name.
  • @property {number} selectionGrade. The priority (weight) of the Badge.
  • @return {Promise(Object)} badge_info. The response object.
  • The response object can contain an "error" property instead of result data.
  • @property {Object} error. The error object.
  • @property {string} badgeId. The id of the Badge. Example: "bdg_2"

CAPIS API Function: LoginManager.findUserLogins(sapId, filterOptions, rpId)

Return type: Promise(Object). Contains some javascript arrays (does NOT return a promise??)

Gets a list of UserLogins, a list of Badges, and their match grade.

Searches through the browser's internal "storage" for UserLogins that meet the RP requirements. (For UserLogins that can be used at the RP.) Only one item in the list will be the "default". (pre-selected for the user) The caller can use this list in a dialog displayed to the user asking which UserLogin to use.

Function info: (parameter list, return value, etc.)
  • @param {string} sapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @param {Object} filterOptions. The filter criteria. To limit the returned list of UserLogins.
  • @property {Array} altSapIdList. A list of alternate sapId items.
  • @property {string} opId. The method (function name) to be performed. ("login", "setActiveCredentials", etc.)
  • @param {string} rpId. The RP identifier. Example: "login.example.com" (limits access to only some RP)
  • @return {Promise(Object)} query_response. The response object. Contains two lists of UserLogins.
  • @property {Array} qualUserLoginList. The list of qualified UserLogins. (That survived filtering.)
  • @property {Array} unqualUserLoginList. The list of un-qualified UserLogins. (That were filtered out.)
  • @property {Array} allBadgeList. The list of User Badges. Each badge contains a list of registered UserLogin.
  • Returns a list of the UserLogins. A list of the User Badges.
Example use:
// arguments:
let filterOptions = { sapId: sapId, serviceDesc: service_info };
let lomaQResultItem = {};
  return LoginManager.findUserLogins(sapId, filterOptions, rpClientData)
  .then( findUL_response => {
    lomaQResultItem.qualList = findUL_response.qualUserLoginList;
    lomaQResultItem.unqualList = findUL_response.unqualUserLoginList;
  });

// Example RP Service Descriptor:
/* Example Auth Service Descriptor
let service_info = { "id": "service_1",
  "protocol": "capis_login_service",
  "endpoints": [
    { "id":"endpoint_1", "sUri":"/_capis/cls/serviceCall", "request_format":"JWS" }
  ],
  "userIdRules": {
    "userIdTypes": ["single_site_userId", "ciq:C:B1:9:ri"]
    // "createMethods": ["assigned_ulc", "claim_ms_ulc"]
  },
  "loginUseRules": {
  },
  "supported": {
    "userAuthScheme": {"methods":["stored_cred", "only_MSUID"]},
    "supported.uic.csvm": ["basic1","basic2"]
  }
}
*/

// output:
matches = [
  {id: "bg1", name:"Super Duper", is_selected:false},
  {id: "bg2", name:"Sergeant Pepper", is_selected:true}
]

CAPIS API Function: LoginManager.importUserLogin(badgeId, exportedLogin, importOptions)

Return type: Promise(Object).

Imports a UserLogin into the browser. (How to import?)

Attempts to add a UserLogin to the internal Badge.

This function returns a Promise. It can fail. The UserLogin can be malformed, or the protocol can be unknown or unsupported.

// Adds a UserLogin to the browser. (How to import?) Callback asks for the private key?
Function info: (parameter list, return value, etc.)
  • @param {string} badgeId. The id of the Badge. Example: "bg2" (Where to store the import.)
  • @param {Object} exportedLogin. The exported UserLogin to import.
  • @param {Object} importOptions. The UserLogin creation options.
  • @property {Object} importOptions.rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @property {Array} importOptions.credSourceCreationList. A list of "Credential Source creation" objects.

CAPIS API Function: LoginManager.createUserLogin(badgeId, sapId, ulCreationOptions, rpId, rpClientData)

Return type: Promise(Object).

Creates a new UserLogin for the RP. Adds it to the specified Badge. Creates all the requested credentials for the UserLogin. Returns the lipId of the new UserLogin. On error, returns an error object.

Function info: (parameter list, return value, etc.)
  • @param {string} badgeId. Where to store the new UserLogin. The id of the Badge. Example: "bdg_2"
  • @param {string} sapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @param {Object} ulCreationOptions. Object containing other creation options.
  • @property {string} disambigName. The new disambiguation name for the UserLogin. (If needed)
  • @property {string} options.initUserId - The initial User Id. Requested by the client.
    Warning: This only sets the *original* userId. (Before the request to the RP.) (Example: If using userid_creation.claim_ms_ulc.)
  • @property {Array} credSourceCreationList. A list of "Credential Source creation" objects.
    @example_object credCreationInfo_item = { "cci":"834", "type":"public-key", "COSE_alg": -7}
  • @param {string} rpId. The RP identifier. Example: "login.example.com"
  • @param {Object} rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @property {string} rpClientData.rpDisplayName. The RP display name. Example: "ACME Corporation"
  • @property {string} rpClientData.challenge. A "cryptographic nonce" value. base64url encoded.
  • @return {Promise(Object)} userLogin_info. The response object.
  • The response object can contain an "error" property instead of result data.
  • @property {Object} error. The error object.
  • @property {string} lipId. The LoginItem Permanent Id. Example: "ug34"
Internal steps:
  • Call generateKeyPair()

CAPIS API Function: LoginManager.getUserLoginDetails(lipId, rpId)

Return type: Promise(Object). The UserLogin object.

Gets the specified UserLogin and the contained credential list.

Returns undefined if the lipId is invalid. If there is no UserLogin for that lipId. (Or if the access restrictions are wrong.)

This does not return the actual credentials. It only returns a list of the credential information. Their ID, type and public keyHandle (if applicable).

Function info: (parameter list, return value, etc.)
  • @param {string} lipId. The LoginItem Permanent Id. Example: "ug34"
  • @param {string} rpId. The RP identifier. Example: "login.example.com" (limits access to only some RP)
  • @return {Promise(Object)} getInfo_response. Will be undefined if the UserLogin is not found.
  • @property {boolean} isRpRegistered. Is true if the UserLogin has been registered with the RP.
  • @property {string} badgeId. The id of the User Badge. Example: "bg2".
  • @property {string} enc_user_id. The encrypted UserId. Example: "ciq:C:B1:1:K8h3_TfXr6ZtLq7d1m8k".
  • @property {string} displayName. The name to display. Only used if multiple UserLogins for the same RP.
  • @property {number} creationDate. The date the UserLogin was created. (Unix timestamp)
  • @property {number} modifiedDate. The date the UserLogin was modified. (Unix timestamp)
  • @property {number} lastLoginDate. The date the UserLogin was last used. (Unix timestamp)
  • @property {number} rpRegDate. The date the UserLogin was registered at RP. (Unix timestamp)
  • (There are only 3 kinds of modification. Change enc_user_id, displayName, or credential list.)
  • @property {Array} activeCredentialIdList. The array of active credential Ids.
  • @example_object activeCredentialIdList = [ "cd2", "cd15", "cd3" ] Composed of only credential ids.
  • @property {Array} activeCredentialDetailList. The array of active credentials.
  • @example_object activeDetailItem = {id:"cd2", type: "public-key"}
  • @property {Array} stagedCredentialIdList. The array of staged credentials.
  • @example_object stagedCredentialIdList = [ "cd2", "cd15", "cd3" ] Composed of only credential ids.
  • @property {Array} completeCredentialList. All the existing credentials for the UserLogin.
  • @example_object completeList_item = {id:"cd2", type: "public-key", COSE_alg: -7}

CAPIS API Function: LoginManager.setUserLoginDetails(lipId, newProperties, rpId)

Return type: Promise(Object). Object containing boolean "isSuccess" property.

Updates the UserLogin with the new info. Can change only 6 things, the "assigned" UserId, the display_name, the badgeId, the "staging" list of credentials, the "confirmed" list of credentials and the "tag list".

The newProperties can contain 6 properties, "updatedUserId", "displayName", "badgeId", "toBeStagedCredentialIdList", "credentialConfirmList" and the "tag list".

Function info: (parameter list, return value, etc.)
  • @param {string} lipId. The LoginItem Permanent Id. Example: "ug34"
  • @param {Object} newProperties. The new property values.
  • @property {string} displayName. The new display name, set by the user. (Only used if a Badge contains multiple UserLogins for the same RP.)
  • @property {string} badgeId. The id of the Badge. Ex: "bg2".
  • @property {Array} toBeStagedCredentialIdList. The (existing) credentials to be staged.
  • @example_object toBeStagedCredentialIdList = [ "cd2", "cd15", "cd3" ] Composed of only credential ids.
  • @property {Array} tagAddList. The list of "tags" to add to the UserLogin.
  • @property {string} rpConfirmation.updatedUserId. The new user id. May be encrypted. Usually given by the RP. (in assignedUserId.)
  • @property {string} rpConfirmation.userIdAssignmentType. Details the updatedUserId. Tells if the userId is encrypted. Etc.
  • @property {Array} rpConfirmation.credentialConfirmList. The credential confirm results from the RP.
    Example: credentialConfirmItem = {id: "cd2", error:"invalid"}
  • @property {string} rpConfirmation.confirmType. Specifies the "confirmed" list item type, and the serviceOp that was performed by the RP. Must be one of "regUserLogin", "setActive", "login", "importUserLogin". (Result after RP registration or login.)
  • @param {string} rpId. The RP identifier. Example: "login.example.com" (limits access to only some RP)
  • @return {Promise(Object)} userLogin_info. The response object.
  • The response object can contain an "error" property instead of result data.
  • @property {Object} error. The error object.
  • @property {string} lipId. The LoginItem Permanent Id. Example: "ug34"

CAPIS API Function: LoginManager.createCredentialSources(lipId, credentialOptions, rpId)

Return type: Promise(Object).
Function info: (parameter list, return value, etc.)
  • @param {string} lipId. The LoginItem Permanent Id. Example: "ug34"
  • @param {Object} credentialOptions. Credential creation options.
  • @property {Object} credentialOptions.rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @property {Array} credentialOptions.credSourceCreationList. A list of "Credential Source creation" objects.
    @example_object credCreationInfo_item = { "cci":"834", "type":"public-key", "COSE_alg": -7}
  • @property {string} rpClientData.challenge. A "cryptographic nonce" value. base64url encoded.
    The challenge may be needed for the newly created credentials to have proper attestation data. The challenge is optional. It is only needed for WebAuthn, where it proves "freshness" of the attestation data.
  • @param {string} rpId. The RP identifier. Example: "login.example.com" (limits access to only some RP)
  • @return {Promise(Object)} createCred_response. The response object.

CAPIS API Function: LoginManager.stageActiveCredentials(lipId, credentialOptions, rpId)

Return type: Promise(Object).

Sets the "first stage" of the active credentials. This is the first step in setting the "active" credentials at the RP. After this function is called, the RP must be sent a "setActiveCredentials" CLS Request. If the RP responds with a success, then the browser will update the "active" credentials in the Login Manager. (The LoginDirector.evaluateServiceResponse() function calls LoginManager.setUserLoginDetails(lipId, newProperties, rpId).)

The input must specify which credentials to use. This is actually two lists, (1) a list of existing credential IDs and (2) a list of new credentials to be created. For each specified new-credential-info, the Login Manager will create a new credential source for use with the specified UserLogin, and add the credential ID to the "createdCredentialList" that is returned. (The credential sources are kept secret internally to the UserLogin. The credential ID and type are returned.)

Returns an object containing two lists. (1) a list of the "created" credential info objects. This list items contain the credential id, the type, and other public settings. (i.e. the algorithm) (2) a list of the "selected" credentials. This contains the credential IDs for credentials that were not created, and previously existed.

Function info: (parameter list, return value, etc.)
  • @param {string} lipId. The LoginItem Permanent Id. Example: "ug34"
  • @param {Object} credentialOptions. Credential selection and creation options.
  • @property {Object} credentialOptions.rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @property {Array} credentialOptions.credSourceCreationList. A list of "Credential Source creation" objects.
    @example_object credCreationInfo_item = { "cci":"834", "type":"public-key", "COSE_alg": -7}
  • @property {Array} existingCredentialIdList. A list of which existing credentials to use.
  • @example_object existingCredentialIdList = [ "cd2", "cd15", "cd3" ] Composed of only credential ids.
  • @param {string} rpId. The RP identifier. Example: "login.example.com" (limits access to only some RP)
  • @return {Promise(Object)} setCred_response. The response object.
  • @property {Array} createdCredentialList. The list of credentials that were created. (id, type)
  • @example_object createdCredItem = { id: "cd14", cci: "834", type: "public-key" }
  • @property {Array} selectedCredentialIdList. The list of staged credentials that already existed.
  • @example_object selectedCredentialIdList = [ "cd2", "cd15", "cd3" ] Composed of only credential ids.

Will create the requested new credentials listed in the "credSourceCreationList".

For new public key attestation, the RP needs a single bit of information about any registration: was this public-key generated in a certified device or not?

CAPIS API Function: LoginManager.buildProofForRp(lipId, opId, rpClientData, buildOptions)

Return type: Promise(Object). The user can quit or cancel the login. The success callback receives a "proof-of-identity" container object. Or null.

Creates a proof-of-identity, for delivery to an RP. Created to meet the RP's requirements.

This function uses the provided "sapId" as the "aud" (audience) field in the proof-of-identity.

Returns a promise. The success callback receives a "proof-of-identity" container object. It contains UP TO 4 items. Either the proof-of-identity, or the UserId Assertion and the values for the UserId certificate.

Function info: (parameter list, return value, etc.)
  • @param {string} lipId. The LoginItem Permanent Id. Example: "ug34"
  • @param {string} opId. The method (function name) for the service to perform. (Ex: "login", "setActiveCredentials", etc.)
  • @param {Object} rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @property {string} rpClientData.rpDisplayName. The RP display name. Example: "ACME Corporation"
  • @property {string} rpClientData.challenge. A "cryptographic nonce" value. base64url encoded.
  • @param {Object} buildOptions. Other options.
  • @property {string} sapId. The id of the UserAuth ServiceApplication. (Used as the "audience".)
  • @property {string} buildOptions.rpId. The RP identifier. Example: "login.example.com"
  • @property {Object} buildOptions.userIdReqInfo - The client requested UserId info.
    Used when opId="createUserLogin" or "changeUserId". (Example: If using userid_creation.claim_ms_ulc.)
  • @property {Object} sessionNotes. Anything special the RP requires from the session.
Internal steps:
  • Determine if the JWS will need a credential_registration section. (This is the case for opId "createUserLogin" and "setActiveCredentials".)
  • If credential_registration is required, then call createNonPublicKeyProofItems.
  • If credential_registration is required, then determine if backup keys are needed.
  • Create the payload. Include the fields that the RP requires.
  • Look up the private key(s) for the UserLogin.
  • Sign the proof-of-identity with the private keys.

Additional option. As part of the process, it may be desirable to create a new key-pair and send the public key to the RP as part of the proof. This key may be used to secure session communication between the browser and the RP. If this is done, the private key must be stored internally to the browser. Example: {lipId:"ug34", RP_domainName:"123done.org", private_key:"xxxx"}

Example use:
// arguments:
lipId = "ug34"
resolvedOptions
buildOptions = {serviceOp:"cls/login", for_future_use:"something..."}

// return value:
a Promise

// Promise resolves to:
proof_assertion = {
uid_cert_chain:[{uic.format:"JWS", uic.csvm:"OIDCD", "ucv": { "payload":"82h7vb...", "signatures": [...] } }]
}
Example implementation code.
// example implementation
function buildProofForRp(lipId, opId, rpClientData, buildOptions) {
  let sapId = buildOptions.sapId;
  let callOptions = buildOptions.callOptions;
  let serviceOp = "cls/" + opId; // Example: "cls/login";
  let slashIndex = serviceOp.indexOf("/");
  let protocol_id = "cls";
  let protocol_id_2 = serviceOp.substring(0, slashIndex);
  let opId_2 = serviceOp.substring(slashIndex + 1)
  let signInput = buildOptions.signInput;
  let active_values = credentialStore_getActiveValues(); // created previously from the options and page settings.
  let service_info = active_values.service_info;
  let proof = {};
  let payload = {};
  let signatures = [];
  proof.payload = payload;
  proof.signatures = signatures;
  payload.protocolId = "cls";
  payload.reqOp = opId;
  // payload.nonce = rpClientData.challenge
  payload.challenge = rpClientData.challenge
  payload.nit = rpClientData.nonceIssueTime;
  payload.redirectUri = callOptions.redirectUri;
  payload.iat = new Date().getTime();
  // payload.uid.clientReqUserId = callOptions.userIdRuleCfg;
  // payload.uic.format = ?;
  // payload.uid_cert_chain = [];
  return Promise.resolve("mmm")
  .then( mmm_response => {
    let signInput2 = payload
    return bLoginManager.createNonPublicKeyProofItems(lipId, rpClientData, signInput2, buildOptions);
  }).then( assert_response => {
    let proof_list = assert_response.assertion.cpl;
    // proof.signatures = proof_list;
    proof_list.forEach( function(item, index, array) {
      let m2 = { header: { kid: item.cpid}, protected: {cpt: item.cpt, cpf: item.cpf}, signature: item.cpv};
      signatures.push(m2);
    });
    credentialStore_storeUserLoginHistory(lipId);
    return proof;
  });
}

CAPIS API Function: CapisLogin.performUserAuth(opId, callOptions)

Return type: Promise(Object). The user can quit or cancel the requested serviceOp.
Example implementation code.
  • @param {string} opId. The method (function name) for the service to perform. (Ex: "login", "setActiveCredentials", etc.)
  • @param {Object} CapisAPI.callOptions. The configuration options for the RP service call.
  • @property {string} redirectUri. The URI to redirect to after the serviceOp.
  • @return {Promise(Object)} prHandlerResponse. The response object. (protocol handler)
  • @property {Object} buildResponse. The data that was built.
  • @property {Object} buildResponse.requestData. The request that was built.
  • @property {Object} serviceResponse. The response from the service.
  • @property {Object} evalResponse. The response from the evaluation.
// example implementation
function performUserAuth(opId, callOptions) {
  // Return an "prHandlerResponse". This may contain (probably contains) a serviceResponse.
  let prHandlerResponse = {};
  prHandlerResponse.callOptions = callOptions;
  let buildContext;
  return this.buildServiceRequest(opId, callOptions)
  .then( buildResponse => {
    buildContext = buildResponse;
    return this.sendRequestToService(buildResponse, buildResponse.requestData);
  }).then( serviceResponse => {
    prHandlerResponse.serviceResponse = serviceResponse;
    CLW_fireEvent("sendRequest", opId, false, callOptions);
    if (!serviceResponse.statusOK) {
      // Error connecting to the service.
      let url = serviceResponse.url;
      let statusCode = serviceResponse.fetch_response.status; // For debug
      let statusText = serviceResponse.fetch_response.statusText;
      throw new Error("Bad response from service. statusCode=" + statusCode + " statusText=" + statusText + " url=" + url);
    } else {
      return bLoginDirector.evaluateServiceResponse2(buildContext, serviceResponse);
      // return bLoginDirector.evaluateServiceResponse(serviceResponse.svRequestId, serviceResponse);
    }
  }).then( evaluate_response => {
    prHandlerResponse.evalResponse = evaluate_response;
    CLW_fireEvent("evaluateResponse", opId, false, callOptions);
    let eval_success = true; // evaluate_response.statusOK
    if (eval_success) {
      // Notify the user that the serviceOp succeeded.
      // Can refresh the page or navigate to a different page.
      // location.reload(); or location.href = callOptions.redirectUri;
    }
    return prHandlerResponse;
  }).catch(error => {
    if (!error.message.startsWith("Action canceled")) {
      se8_debug.log("Error in CapisLogin.performUserAuth error=" + error.message);
    }
    return Promise.reject(error);
  });
}

CAPIS API Function: CapisLogin.buildServiceRequest(opId, callOptions)

Return type: Promise(Object). The user can quit or cancel the login.

This function is a small wrapper for LoginDirector.buildServiceRequest(clientConfig, opId, callOptions). It exists to allow browser extensions a place to implement additional functionality before calling the "unmodifiable" LoginDirector functions.

Installed extensions can redefine this function. Since this function returns a promise, the new functionality can even include an online API call. For example, it could query an online storage system that stores identities for the user. And the online API call could be done only if the original function fails.

Function info: (parameter list, return value, etc.)
  • @param {string} opId. The method (function name) for the service to perform. (Ex: "login", "setActiveCredentials", etc.)
  • @param {Object} CapisAPI.callOptions. The configuration options for the RP service call.
  • @property {string} callOptions.redirectUri. The URI to redirect the user to after the serviceOp.
  • @property {Object} criteriaChangeSet. The changes to make to the UIC. Only used with opId "createUserLogin", "setActiveCredentials"
  • @return {Promise(Object)} buildResponse.
  • @property {Object} requestData. The request that was built.
  • @example_object requestData = { JWA: {payload:"xxx", signatures:[{mm:"xx"}] } }
  • @property {Object} clsServiceConfig. The CLS service configuration. (The ServiceDescriptor, etc.)

!!!!This function can show popup dialogs or redirect the user.!!!!

Internal steps:
Example implementation code.
// example implementation
function buildServiceRequest(opId, callOptions) {
  let rpClientData = {origin: window.location.origin, pathname: window.location.pathname, allowSOWA: false};
  return capisControl_api.ensureClientConfig()
  .then( clientConfig => {
    rpClientData.challenge = clientConfig.publicOptions.challenge;
    rpClientData.nonceIssueTime = clientConfig.publicOptions.nonceIssueTime;
    let sapId = clientConfig.activeSapId;
    let clientConfig2 = Object.assign({}, clientConfig);
    // clientConfig2.opId = opId;
    clientConfig2.rpClientData = rpClientData;
    return loginDirector_api.buildServiceRequest(clientConfig2, opId, callOptions);
  }).then( buildResponse => {
    // check values
    return buildResponse;
  });
}

CAPIS API Function: CapisLogin.sendRequestToService(buildContext, requestData)

Return type: Promise(Object).

Sends the requestData object to the RP endpoint. In whatever manner the RP designated in the RP Config Document.

Function info: (parameter list, return value, etc.)
  • @param {Object} buildContext. The build context data. (The buildResponse from buildServiceRequest.)
  • @param {Object} requestData. The data to be sent to the RP service. Contains the "proof of identity", etc.
  • @return {Promise(Object)} serviceResponse. The response object.
  • @property {boolean} statusOK. If the service returned an OK status.
  • @property {string} url. The URL that was contacted by the request.
  • @property {Object} jsonData. The json data that was returned from the service.
  • @property {Object} fetch_response. The wrapped fetch response object.
Example use:
// arguments:
let callOptions = {
  "protocolId": "cls",
  "reqOp": "login",
uid_cert_chain:[{ uic.format:"JWS", uic.csvm:"OIDCD", "ucv": { "payload":"82h7vb...", "signatures": [...] } }],
redirectUri:"http://example.com/some/path/page.html" }; return capisLogin_api.buildServiceRequest("login", callOptions) .then( buildResponse => { let requestData = buildResponse.requestData; return capisLogin_api.sendRequestToService(buildResponse, requestData); }).then( serviceResponse => { if (serviceResponse.statusOK) ... });
Example implementation code.
// example implementation
function sendRequestToService(buildContext, requestData) {
  let serviceResponse;
  let opId = buildContext.opId;
  let serviceOp = "cls/" + opId;
  return loginDirector_api.sendRequestToService(buildContext, requestData)
  .then(serviceResponse => {
    CLW_fireEvent("sendRequest", opId, false, serviceResponse);
    let jsonData = serviceResponse.jsonData;
    let statusOK = serviceResponse.statusOK;
    return serviceResponse;
  }).catch(error => {
    console.log("Error in sendRequestToService. error=" + error.message);
    return Promise.reject(error);
  });
}

CAPIS API Function: CapisLogin.evaluateServiceResponse(svRequestId, serviceResponse)

Return type: Object.

Update the Login Status at the RP, add the result to history.

Function info: (parameter list, return value, etc.)
  • @param {string} svRequestId. The ID of the request sent to an RP service. Ex: "264"
  • @property {Object} clientContext. The context of the client. Ex: The HTML page that made the call.
  • @param {Object} serviceResponse. The response sent from the RP service.
  • @return {Promise(Object)} eval_response. The response object.
  • @property {Object} serviceResponse. The serviceResponse object that was passed in as an argument.
// example implementation
function evaluateServiceResponse(svRequestId, serviceResponse) {
  let request_context1 = CL_getServiceRequestContext(svRequestId);
  return loginDirector_api.evaluateServiceResponse(request_context1, serviceResponse)
  .then( eval_response => {
    CL_fireEvent(...);
    return eval_response;
  });
}

CAPIS API Function: CapisLogin.getLoginStatus()

Return type: Object.

Gets the current Login Status at the RP, the serviceDesc, etc. (Which service was used to login.) This function does NOT return the lipId. It does not return the raw UserId.

Function info: (parameter list, return value, etc.)
  • @internal {string} sapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @return {Object} loginStatusInfo. Contains the login status info.
  • @property {string} sapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @property {string} lipId. The LoginItem Permanent Id is NOT available. Example: "ug34"
  • @property {Object} clsServiceConfig. The CLS service configuration. (The ServiceDescriptor, etc.)
  • @property {string} sessionUserId. The temporary UserId that is logged in.
  • @property {number} statusCode. Example: 2 = logged_out
  • @example_object loginStatus = {sapId:sapId, sessionUserId:"none", statusCode:2} (2="logged_out")

The login status is a number. 1 = logged_in, 2 = logged_out.

This function does NOT return the lipId or the raw UserId, because that information is secret / protected. The lipId MUST NOT be known to the RP. Because the RP can use it to identify the Authenticator. (The lipId for the RP is unique to the Authenticator.) For added security, the raw UserId SHOULD not be known to the browser User Agent, as a modified user agent can record the UserId. (And not delete it after use.) As a potential security precaution, a sessionUserId is created and used in the proof of identity, so that the raw UserId is not revealed to the User Agent. If the sessionUserId were not used, then a browser would be given the real UserId that is used to login to the RP. An insecure or modified browser could record the UserId and/or transmit it to a third party, etc. Once a UserId is known, various means can be attempted to compromise the password / private key.

// example implementation
function getLoginStatus() {
  let sapId = CLP_getStoredSapId();
  // let sapId = clientConfig.activeSapId;
  if (sapId === undefined) {
    return {hasError: true, isLoggedIn: undefined, error: "Not initialized. The current sapId is unknown."};
  }
  let loginStatusInfo = loginDirector_api.getLoginStatus(sapId);
  CL_fireEvent(...);
  return loginStatusInfo;
}

CAPIS API Function: CapisLogin.logoutAll()

Return type: Promise(Object)??.

Sends a logout request to all logged-in "auth" websites. This function is callable by users via the toolbar, etc. (calls logout on all logged-in websites)

Example use:
// arguments
capisLogin_api.logoutAll(); // Note the function does not take callOptions as an argument.

CAPIS API Function: CapisLogin.addEventListener(event_name, callback, options)

Return type: Object. {failureReason: "alreadyExists"}

Details here.

CAPIS API Function: CapisLogin.removeEventListener(event_name, callback, options)

Return type: Object. {removeCount: 1}

Details here.

CAPIS API Function: CapisLogin.importUserLogin(lomaId, badgeId, exportedLogin, importOptions)

Return type: Promise(Object).

Imports a UserLogin into the browser. (How to import?)

Attempts to add a UserLogin to the internal Badge.

This function returns a Promise. It can fail. The UserLogin can be malformed, or the protocol can be unknown or unsupported.

Note, installed extensions can redirect this function to add identities to an online storage system.

Function info: (parameter list, return value, etc.)
  • @param {string} lomaId. The LoginManager identifier. (Where to store the import.)
  • @param {string} badgeId. The id of the Badge. Example: "bg2" (Where to store the import.)
  • @param {Object} exportedLogin. The exported UserLogin to import.
  • @param {Object} importOptions. The UserLogin creation options.
  • @property {Object} importOptions.rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @property {Object} importOptions.credSourceCreationList. A list of "Credential Source creation" objects.
  • @return {Promise(Object)} import_response. The response object.
  • @property {boolean} isSuccess. If the function was a success.
// example implementation
function importUserLogin(x, y, z) {
  let sapId;
  return capisControl_api.ensureClientConfig()
  .then( clientConfig => {
    sapId = clientConfig.activeSapId;
    return loginDirector_api.importUserLogin(sapId, x, y, z);
  }).then( import_response => {
    CL_fireEvent(...);
    return import_response;
  });
}

CAPIS API Function: CapisLogin.setDefaultUser(browser_user)

Return type: Promise(Object).

Sets the "default" user. Must be a browser user_profile. This does NOT authenticate the user or connect to any LoginManagers. During authentication, the specified user's authentication prompt is displayed.

CAPIS API Function: CapisLogin.changeUser(browser_user)

Return type: Promise(Object).

Change the currently active user in the browser. This will perform a "logoutAll" to close all active login sessions. Then it will change the current User profile used to login to RPs, and call CapisLogin.promptToConnectLM.

CAPIS API Function: CapisLogin.promptToConnectLM(browser_user)

Return type: Promise(Object).

Display the browser's popup dialog, asking the user to connect to any LoginManagers. The argument "browser_user" is optional. If it is not supplied, then the default_browser_user is used.

Function info: (parameter list, return value, etc.)
  • @param {string} browser_user. The current user that is logged into the browser.
  • @return {Promise(Object)} connectToLoma_response. The response object.
  • @property {boolean} isSuccess. If the function was a success.

CAPIS API Function: CapisLogin.disconnectLoginManagers(lomaIdList)

Return type: Promise(Object).
Function info: (parameter list, return value, etc.)
  • @param {Array} lomaIdList. The list of LoginManager identifiers to disconnect.
    The lomaIdList can also be the special value "all".
  • @return {Promise(Object)} disconnectLomaList_response. The response object.
  • @property {boolean} isSuccess. If the function was a success.

CAPIS API Function: CapisLogin.acquireNewUserIdCertificate(UserId)

Return type: Promise(Object).

Get a new User Id Certificate, from the Identity Provider. This will probably require the user to re-prove themselves to the IdP. (re-enter their password, etc.)

CAPIS API Function: CapisLogin.getUserIdCertificate(UserId)

Return type: Promise(Object).

Get the cached User Id Certificate from the browser.

CAPIS API Function: LoginDirector.buildServiceRequest(clientConfig, opId, callOptions)

Return type: Promise(Object). The user can quit or cancel the login.

This function is a small wrapper for LoginManager.buildProofForRp(). It exists to allow browser extensions a place to implement additional functionality before calling the "unmodifiable" LoginManager functions.

Function info: (parameter list, return value, etc.)
  • @param {Object} clientConfig. The client configuration. Ex: The HTML page that made the call.
  • @property {string} clientConfig.activeSapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @property {Object} clientConfig.clsServiceConfig. The CLS service configuration. (The ServiceDescriptor, etc.)
  • @property {Object} clientConfig.rpId. The RP identifier. Example: "login.example.com"
  • @property {Object} clientConfig.rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @property {string} rpClientData.rpDisplayName. The RP display name. Example: "ACME Corporation"
  • @property {string} rpClientData.challenge. A "cryptographic nonce" value. base64url encoded.
  • @param {string} opId. The method (function name) for the service to perform. (Ex: "login", "setActiveCredentials", etc.)
  • @param {Object} CapisAPI.callOptions. The configuration options for the RP service call.
  • @property {string} redirectUri. The URI to redirect the user to after the serviceOp.
  • @property {Object} criteriaChangeSet. The changes to make to the UIC. Only used with "cls/createUserLogin", "cls/setActiveCredentials"
  • @return {Promise(Object)} buildResponse.
  • @property {Object} requestData. The request that was built.
  • @example_object requestData = { JWA: {payload:"xxx", signatures:[{mm:"xx"}] } }
  • @property {Object} clsServiceConfig. The CLS service configuration. (The ServiceDescriptor, etc.)

!!!!This function can show popup dialogs or redirect the user.!!!!

Internal steps:
Example implementation code.
// example implementation
function buildServiceRequest(clientConfig, sapId, opId, callOptions) {
  let lipId;
  let lomaId;
  // let sapId_2 = clientConfig.sapId;
  let opId2 = opId; // One of "login", "setActiveCredentials", etc.
  let rpClientData = clientConfig.rpClientData;
  return Promise.resolve("mmm_response")
  .then( mmm_response => {
    if (opId == "login") {
      let selectionOptions = {}; selectionOptions.stuff = "some_stuff";
      return this.selectUserLogin(selectionOptions, callOptions)
    } else { ... }
  }).then( selection_response => {
    lipId = selection_response.lipId;
    lomaId = selection_response.lomaId;
    let buildOptions = {};
    buildOptions.callOptions = callOptions;
    buildOptions.sapId = sapId;
    let loginManager_api = A2_getLoginManager(lomaId);
    return loginManager_api.buildProofForRp(lipId, opId, rpClientData, buildOptions);
  }).then( proof => {
    // check values
    let build_response = {};
    // build_response.requestData = proof;
    build_response.requestData = { JWS: proof.JWS};
    build_response.serviceDesc = buildOptions.serviceDesc;
    build_response.callOptions = callOptions;
    build_response.opId = opId;
    return build_response;
  });
}

CAPIS API Function: LoginDirector.sendRequestToService(buildContext, requestData)

Return type: Promise(Object).

Sends the CLS Request to the RP service.

Sends the requestData object to the RP endpoint. In whatever manner the RP designated in the RP Config Document.

Function info: (parameter list, return value, etc.)
  • @param {Object} buildContext. The service request context information from buildServiceRequest.
  • @property {Object} clientConfig. The client configuration. (for the HTML page.)
  • @property {Object} clsServiceConfig. The CLS service configuration. (The ServiceDescriptor, etc.)
  • @property {string} buildContext.sapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @property {string} buildContext.opId - The method (function name) for the service to perform. Ex: "login"
  • @property {Object} rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @param {Object} requestData. The data to be sent to the RP service. Contains the "proof of identity", etc.
  • @return {Promise(Object)} serviceResponse. The response object.
  • @property {boolean} statusOK. If the service returned an OK status.
  • @property {string} url. The URL that was contacted by the request.
  • @property {Object} jsonData. The json data that was returned from the service.
  • @property {Object} fetch_response. The wrapped fetch response object.
Example implementation code.
// example implementation
function sendRequestToService(buildContext, requestData) {
  let transport_response = {};
  let clientConfig = buildContext.clientConfig;
  let sapId = buildContext.sapId;
  let opId = buildContext.opId;
  let clsServiceConfig = buildContext.clsServiceConfig;
  // let protocol_id = "cls";
  // let clsServiceConfig = LDI_getServiceConfigFromClientConfig(protocol_id, clientConfig);
  let serviceDesc = clsServiceConfig.serviceDesc_fromPrimary;
  return Promise.resolve("mmm")
  .then( mmm_respose => {
    let buildValues = CLD_getBuildValues(buildContext.buildId);
    let lipId = buildValues.lipId;
    let lomaId = buildValues.lomaId;
    // itemRecordDatabase.recordAction(lomaId, lipId, actionOptions);
    let active_endpoint = serviceDesc.endpoints[0];
    let sUri = active_endpoint.sUri;
    // Note: Different implementations may split the requestData up into multiple parameters.
    let templateList = [{name:"capis_request", type:"json_object"}];
    let item_0 = Object.assign({}, templateList[0], {value: requestData});
    let dataParamList = [item_0];
    if (!(active_endpoint.method === undefined)) { active_endpoint.method = "POST"}
    let fetch_url;
    let fetch_init;
    let http_method = active_endpoint.http_method;
    if (http_method == "POST") {
      fetch_url = active_endpoint.sUri;
      let body_data = {};
      dataParamList.forEach( (item,index) => { body_data[item.name] = item.value; });
      fetch_init = {method:"POST", body: body_data};
      fetch_init.headers = { 'content-type': 'application/json' };
    } else if (http_method == "GET") {
      // let query_str = createQueryString(dataParamList);
      let query_str = "";
      dataParamList.forEach( (item,index) => {
        if (index != 0) query_str += "&";
        query_str += encodeURIComponent(item.name) + "=" + encodeURIComponent(JSON.stringify(item.value));
      });
      fetch_url = active_endpoint.sUri + "?" + query_str;
      fetch_init = {method:"GET"};
    } else {
      throw new Error("Cannot send request. Invalid protocol=" + http_method);
    }
    // Fetch API, not supported by older browsers.
    return fetch(fetch_url, fetch_init);
  }).then( fetch_response => {
    transport_response.fetch_response = fetch_response;
    transport_response.url = fetch_response.url;
    transport_response.statusCode = fetch_response.status;
    transport_response.statusOK = false;
    if (!fetch_response.ok) {
      return undefined;
    }
    return fetch_response.json();
  }).then( json_response => {
    if (json_response !== undefined) {
      transport_response.jsonData = json_response;
      transport_response.statusOK = true;
    }
    return transport_response;
  }).catch(error => {
    console.log("Error in sendRequestToService. error=" + error.message);
    return Promise.reject(error);
  });
}

CAPIS API Function: LoginDirector.evaluateServiceResponse(svRequestId, serviceResponse)

Return type: Object.

Evaluates the CLS Response, sent to the browser in response to the CLS Request.

Update the Login Status at the RP, add the result to history. Calls the LoginDirector.updateLoginStatusValues function.

If the serviceOp is "cls/createUserLogin" (or "setActiveCredentials"), this function call LoginManager.setUserLoginDetails(lipId, newProperties, rpId).

Function info: (parameter list, return value, etc.)
  • @param {string} svRequestId. The ID of the request sent to an RP service. Ex: "264"
  • @property {Object} clientConfig. The client configuration. (for the HTML page.)
  • @property {Object} clientConfig.rpId. The RP identifier. Example: "login.example.com"
  • @property {Object} clsServiceConfig. The CLS service configuration. (The ServiceDescriptor, etc.)
  • @property {string} sapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @property {string} opId - The method (function name) for the service to perform. Ex: "login"
  • @property {Object} rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @property {Object} requestData. The data that was sent to the RP service. Contains the "proof of identity", etc.
  • @param {Object} serviceResponse. The response sent from the RP service.
  • @return {Promise(Object)} eval_response. The response object.
  • @property {Object} serviceResponse. The serviceResponse object that was passed in as an argument.

CAPIS API Function: LoginDirector.getLoginStatus(sapId)

Return type: Object.

Gets the current Login Status at the RP, the serviceDesc, etc. (Which service was used to login.) This function does NOT return the lipId. It does not return the raw UserId.

Function info: (parameter list, return value, etc.)
  • @param {string} sapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @return {Object} loginStatusInfo. Contains the login status info.
  • @property {string} sapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @property {string} lipId. The LoginItem Permanent Id is NOT available. Example: "ug34"
  • @property {Object} clsServiceConfig. The CLS service configuration. (The ServiceDescriptor, etc.)
  • @property {string} sessionUserId. The temporary UserId that is logged in.
  • @property {number} statusCode. Example: 2 = logged_out
  • @example_object loginStatus = {sapId:sapId, sessionUserId:"none", statusCode:2} (2="logged_out")

The login status is a number. 1 = logged_in, 2 = logged_out.

// example implementation
function getLoginStatus(sapId) {
  let loginStatusInfo = rpLoginStatusManager.getLoginStatus(sapId);
  if (loginStatusInfo === undefined) {
    let loginStatusInfo2 = {noRecord: true, isLoggedIn: false};
    return loginStatusInfo2;
  }
  return loginStatusInfo;
}

CAPIS API Function: LoginDirector.importUserLogin(lomaId, badgeId, exportedLogin, importOptions)

Updates the "ActiveLogin" status list. Return type: Promise(Object).
Function info: (parameter list, return value, etc.)
  • @param {string} lomaId. The LoginManager identifier. (Where to store the import.)
  • @param {string} badgeId. The id of the Badge. Example: "bg2" (Where to store the import.)
  • @param {Object} exportedLogin. The exported UserLogin to import.
  • @param {Object} importOptions. The UserLogin creation options.
  • @property {Object} importOptions.rpClientData. The collected client data. Example: {displayName, ancPolicy, challenge}
  • @property {Object} importOptions.credSourceCreationList. A list of "Credential Source creation" objects.
  • @return {Promise(Object)} import_response. The response object.
  • @property {boolean} isSuccess. If the function was a success.

CAPIS API Function: LoginDirector.logoutAll()

Return type: Promise(Object)??. Updates the "ActiveLogin" status list.

CAPIS API Function: LoginDirector.selectUserLogin(selectionOptions, callOptions)

Return type: Promise(Object). The user can quit or cancel the login.

This may display a dialog and ask the user what credential to use. There may be a setting to use a specific credential. Or, to use the only matching credential.

!!!!This function may show popup dialogs or redirect the user.!!!!

Function info: (parameter list, return value, etc.)
  • @param {Object} selectionOptions. The set of criteria to filter and select a UserLogin.
  • @property {Object} clientConfig. The current capis values for the HTML page/window.
  • @property {Object} clsServiceConfig. The CLS service configuration. (The ServiceDescriptor, etc.)
  • @property {string} sapId. The id of the UserAuth ServiceApplication. Example: "login.example.com"
  • @param {Object} options. Other options.
  • @property {Object} clsServiceConfig. The CLS service configuration. (The ServiceDescriptor, etc.)
Internal steps:
  • Call LoginManager.findUserLogins(sapId, filterOptions, rpClientData)
  • May call LoginDirector.displayUserLoginChooser
Example use:
// arguments:
  // Example Promise resolves to:
  let lipId;
  let callOptions = { serviceDesc: service_info };
  return LoginDirector.selectUserLogin(selectionOptions, callOptions)
  .then( selectUserLogin_response => {
    lipId = selectUserLogin_response.lipId;
  });
Example implementation code.
// example implementation
function selectUserLogin(selectionOptions, callOptions) {
  let sapId = selectionOptions.sapId;
  let selectionOptions = {};
  let storageOptions;
  let altOptions; // OK if it is undefined.
  let filterOptions = {sapId: sapId};
  let rpClientData = selectionOptions.rpClientData;
  return LoginManager.findUserLogins(sapId, filterOptions, rpClientData)
  .then( getQualified_response => {
    selectionOptions.regUserLoginArray = getQualified_response.qualUserLoginList;
    selectionOptions.unregUserLoginArray = getQualified_response.unqualUserLoginList;
    storageOptions = {unregBadgeArray: getQualified_response.unregBadgeArray};
    return LoginDirector.displayUserLoginChooser(selectionOptions, storageOptions, altOptions);
  }).then( chooseUserLogin_response => {
    return {lipId: chooseUserLogin_response.chosen_lite_id};
  });
}

CAPIS API Function: LoginDirector.displayUserLoginChooser(selectionOptions, storageOptions, altOptions)

Return type: Promise(Object). The user can quit or cancel the login.

Asks the user which UserLogin to use.

Shows a dialog to the user with three lists, and asks which option to use. A list of UserLogins, a list of creation/storage options, and a list of alternate sources.

Internal steps:
  • Displays the three lists to the user in a popup dialog.
  • The dialog asks the user to select a UserLogin, or to add a new one.

CAPIS API Function: LoginDirector.selectActiveCredentials(sapId, lipId, loginItemInfo, options)

Return type: Promise(Object). This function returns undefined if the user canceled the operation.

Changes which user credentials are "active". (used to authenticate the user. For login, etc.) Creates a new "set" which contains references to existing credentials. Returns an object with "add", "remove" and "create" properties. The first 2 are lists containing existing credential references. The "create" property is a list of credential creation instructions.

This function can return (1) multiple selected credentials, and (2) multiple new credential creation instructions. (Instructions to create public key pairs or passwords etc.) This function is used by the createUserLogin and setActiveCredentials opId. This function may display a dialog to the user, asking for their input. (To select credentials or create new credential instructions. A password, etc.) The dialog should contain the number and type of credentials and Credential Verification Rule that are required and supported by the RP. (i.e. Display to the user the RP requirements.)

CAPIS API Function: LoginDirector.updateLoginStatusValues(sapId, req_context)

Return type: Promise(Object).

Update the Login Status at the RP, add the result to history.

CAPIS API Function: LoginDirector.promptToConnectLM(browser_user)

Return type: Promise(Object).

Display the browser's popup dialog, asking the user to connect to any LoginManagers. The argument "browser_user" is optional. If it is not supplied, then the default_browser_user is used.

Function info: (parameter list, return value, etc.)
  • @param {string} browser_user. The current user that is logged into the browser.
  • @return {Promise(Object)} connectToLoma_response. The response object.
  • @property {boolean} isSuccess. If the function was a success.

CAPIS API Function: LoginDirector.disconnectLoginManagers(lomaIdList)

Return type: Promise(Object).
Function info: (parameter list, return value, etc.)
  • @param {Array} lomaIdList. The list of LoginManager identifiers to disconnect.
    The lomaIdList can also be the special value "all".
  • @return {Promise(Object)} disconnectLomaList_response. The response object.
  • @property {boolean} isSuccess. If the function was a success.

APPENDICES

========

APPENDIX A - Attribution

Changes to the HTML specification

  1. Defined 2 attributes for CAPIS Link. rel="capis-base" and "capis-config". (Alternately, "capis-config" could instead be defined as a "data" attribute, "data-capis-config".)
  2. Defined 2 attributes for CAPIS Anchor. rel="capis-trigger" and "capis-config".
  3. Defined 2 attributes for CAPIS Form. handling="capis-trigger" and "capis-config".
  4. Defined a special behavior for CAPIS HTML Elements. (Calls CapisControl.activateTrigger(htmlElement)

Note: During a CAPIS Form submission, CAPIS will also send an extra, special HTTP parameter, in addition to any regular form data. The default name of the HTTP parameter is capis_request. See endpoint.parameterList.

========