P. Madsen
Ping Identity
A. Jain
VMware
A. Zmolek
Google
T. Bradley
Ping Identity
May 20, 2015

OpenID Connect Native Application Token Agent Core 1.0
draft-native-application-agent-core-01

Abstract

OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and RESTful manner.

The OpenID Connect Native Application Token Agent is a profile of the OpenID Connect Standard 1.0 specification designed to enable 'authorization agents' on devices, ie native applications that obtain OAuth access tokens on behalf of other native applications.


Table of Contents

1. Introduction

OpenID Connect Native Application Token Agent Core 1.0 is a profile of the OpenID Connect Core 1.0 [OpenID.Core] specification that stipulates how a specialized OpenID Connect Client called an Token Agent can obtain tokens on behalf of other installed native applications - thereby provisioning tokens to those applications and so enabling a Single SignOn experience for End-Users.

1.1. Requirements Notation and Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].

Throughout this document, values are quoted to indicate that they are to be taken literally. When using these values in protocol messages, the quotes MUST NOT be used as part of the value.

1.2. Terminology

This specification uses the terms "Access Token", "Refresh Token", "Authorization Code", "Authorization Grant", "Authorization Server", "Authorization Endpoint", "Client", "Client Identifier", "Client Secret", "Protected Resource", "Resource Owner", "Resource Server", and "Token Endpoint" defined by OAuth 2.0 [RFC6749]. This specification also defines the following terms:

Token Agent (TA)
A native application that obtains access tokens on behalf of other native applications - thereby enabling a Single SignOn experience for Native Application end users because the End-Users need only explicitly authenticate the TA once per Authorization Server.
AppInfo Endpoint
A protected resource that the TA can call (using its primary access token) to obtain metadata corresponding to a set of applications - both web & native. The TA uses the application metadata in order to obtain secondary access tokens for those applications.
Primary Token
An OAuth token (access, refresh, and id_token) obtained by the TA for its own uses.
Secondary Token
An OAuth access token obtained by the TA on behalf of another native application.

2. Overview

More and more applications, both enterprise on-prem and cloud-based, are accessed through REST APIs in addition to, or instead of, browser-based access. Mobile clients will be a key consumer of such APIs. Native installed applications (e.g for iOS , Android, BlackBerry, etc devices) offer an important alternative to web or browser-based applications. Both models have their pros/cons.

OAuth 2.0 is an authentication & authorization framework for such REST APIs. Critically, OAuth 2.0 is explicitly designed to support the variety of different client types that will be accessing REST APIs - both applications running on web servers within the enterprise calling out to the cloud/partners etc, as well as applications running on mobile phones belonging to employees and customers. OAuth supports this variety of client types by defining multiple mechanisms for 'getting a token', the different mechanisms acknowledging the constraints of particular client types.

For accessing protected resources behind an API using OAuth for authentication, the mobile application requires an access token - this to be presented on the HTTP calls to the API.

The high-level sequence by which the client obtains and uses an access token is:

The presumption is that each native application client will perform the above steps. When a User has multiple native applications on their device (as is more and more the case) this may be an unacceptable usability burden.

This burden can be reduced by introducing an 'authorization agent' (TA) onto the device. Rather than each native application directly obtaining its own OAuth tokens, the direct token retrieval is assumed by the authorization agent, with the tokens then handed over to the native applications for their normal use. Rather than the user individually authenticating and authorizing each native application, they do so only for the authorization agent - this then bootstrapping subsequently obtaining tokens for the other native applications. Because the User only authenticates and authorizes the authorization agent, the usability burden is significantly reduced.

The TA model is shown below

   
+-------------+
| Device      |       
| +--------+  |                                         +-----------+
| |        |-------- Login & Authorization (1)--------->|           |
| |        |  |                                         |           |
| |  Token |<------ Primary Tokens for TA - (2)---------|           |
| |  Agent |  |                                         |     AS    |
| |        |---- Request Secondary tokens for apps (3)->|           |
| |        |  |                                         |           |
| |        |<-------Secondary Tokens for apps (4)-------|           |
| |        |  |                                         +-----------+
| +--------+  |                                            /\    /\
|    /\       |                                             |    |
|    | Pass   |                                   Validate tokens (7)
|    |Tokens  |                                             |    |
|    \/ (5)   |                                            \/    |
| +--------+  |                                          +-----+ |
| |  App1  | -|--------- API Call with token (6)-------> | RS1 | |
| +--------+  |                                          +-----+ \/
| +--------+  |                                          +---------+
| |  App2  | -|--------- API Call with token (6)-------> |  RS2    |
| +--------+  |                                          +---------+
| +--------+  |                                          +----------+
| |  App3  | -|--------- API Call with token (6)-------> |    RS3   |
| +--------+  |                                          +----------+
+-------------+                                         
                                          
            

Figure 1

Note: the token validation of Step 7 may require a call to the issuing AS (as shown) or may be achieved locally via a digital signarture verification.

A TA must be able to obtain tokens (both primary & secondary) from Authorization Servers. This specification profiles the OpenID Connect Standard 1.0 specification for those interactions. The TA engages in messaging with the relevant Authorization Servers according to this profile in order to obtain the secondary OAuth access tokens on behalf of other native applications.

3. Deployment Models

The authorization agent model can be applied for two different categories of native applications

  1. multiple native applications that call APIs associated with a single policy domain, e.g. multiple native applications created by a consumer retailer or SaaS provider.
  2. multiple native applications that call APIs associated with different policy domains, e.g. multiple applications used by an enterprise employee to access SaaS services relevant to their role.

While both scenarios imply the User authenticating and authorizing each native application individually, in the first case the User would interact with the same AS each time. In the latter, it would be different ASs.

4. Token Agent Authentication

A TA MUST authenticate to the AS both when obtaining primary or secondary tokens.

5. Token Agent Registration

A TA is a specialized OpenID Connect Client and, as such, MUST be registered with an AS.

This profile does not dictate a particular registration model but registration MUST result in the TA having client credentials to be used on the subsequent protocol flows defined here, ie. to obtain both primary & secondary tokens.

OpenID Connect Dynamic Client Registration 1.0 [OpenID.Registration] MAY be used to provide individual client_id and credentials for each instance of a TA.

6. ID Token

The ID Token is a security token that contains Claims about the authentication event and other requested Claims. The ID Token is represented as a JSON Web Token (JWT) [RFC7519].

The ID Token is used to manage the authentication event. The user is passed as the value of sub is scoped to the iss.

The ID Token is audience restricted to either the TA or a remote AS via the aud (audience) Claim.

In the TA model, id_token may have two different types of aud (audience).

  1. one targeted at the TA, returned to it in exchange for the authz code.
  2. one targeted at a remote AS, returned to the TA in exchange for a refresh token. The TA exchanges such an id_token at the corresponding remote AS using an assertion flow for a secondary access token.

The following is a non-normative example of a base64url decoded ID Token with the TA as the value of aud (with line wraps for display purposes only):

  {
   "iss": "https://server.example.com",
   "sub": "24400320",
   "aud": "TA-client-ID",
   "exp": 1311281970,
   "iat": 1311280970
  }

The following is a non-normative example of a base64url decoded ID Token with the remote AS as the value of aud and the TA as the value of azp (with line wraps for display purposes only):

  {
   "iss": "https://server.example.com",
   "sub": "24400320",
   "azp": "TA-client-ID",
   "aud": "https://server.partner.com",
   "exp": 1311281970,
   "iat": 1311280970
  }

7. Protocol Flows

This section details the various protocol flows that the TA and other actors engage in.

7.1. Primary Token Retrieval

The TA first performs an OpenID Connect flow to obtain its own primary tokens. The TA MUST use the code flow, which consists of the following steps:

  1. TA prepares an Authorization Request containing the desired request parameters.
  2. TA sends a request to the Authorization Server.
  3. Authorization Server authenticates the End-User.
  4. Authorization Server obtains the End-User Consent/Authorization.
  5. Authorization Server sends the End-User back to the TA with a code.
  6. TA sends the code to the Token Endpoint to receive primary Access Token, Refresh Token and ID Token in the response.

7.1.1. Token Agent Prepares Authorization Request

To initiate obtaining primary tokens, the TA prepares an Authorization Request to the Authorization Endpoint.

The scheme used in the Authorization Endpoint URL MUST be HTTPS.

Clients MAY construct the request using the HTTP GET or the HTTP POST method.

This profile further constrains the following request parameters:

response_type
This value MUST be code.

Other REQUIRED parameters in the request include the following:

client_id
OAuth 2.0 Client Identifier for the TA.
scope
OAuth 2.0 scope value. It MUST include openid as one of the space delimited ASCII strings.
It MUST also include napps.
redirect_uri
Redirection URI to which the response will be sent. This MUST be pre-registered with the provider.

The following is a non-normative example of an Authorization Request URL (with line wraps for display purposes only):

  https://server.example.com/authorize?
    response_type=code
    &client_id=s6BhdRkqt3
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &scope=openid%20napps

7.1.2. Token Agent Sends Request to Authorization Server

Having constructed the Authorization Request, the TA sends it to the Authorization Endpoint. This MAY happen via HTTPS redirect, hyperlinking, or any other secure means of directing the User-Agent to the URL.

7.1.3. Authorization Server Authenticates End-User

The authorization server authenticates the resource owner to make sure that the consent is obtained from the right party. The exact method of how the authentication is performed is out of scope of this specification.

7.1.4. Authorization Server Obtains End-User Consent/Authorization

The Authorization Server MAY obtain an authorization decision. This can done by presenting the End-User with a dialogue that allows the End-User to recognize what he is consenting to and obtain his consent or by establishing consent via other means (for example, via previous administrative consent).

The openid scope value declares that this OAuth 2.0 request is an OpenID Connect request.

The napps scope value declares that the TA is requesting tokens that can be used to obtain other secondary tokens for those applications relevant to the End-User.

7.1.5. Authorization Server Sends End-User Back to Trust Agent

Once the authorization is determined, the Authorization Server returns a successful response or an error response.

7.1.5.1. Success Case - End-User Granted Authorization

If the Resource Owner grants the authorization request initiated by the TA, the Authorization Server issues a code and delivers it to the TA by adding the following query parameters to the query component of the redirection URI using the application/x-www-form-urlencoded format as defined in Section 4.1.2 of OAuth 2.0 [RFC6749].

code
REQUIRED. OAuth 2.0 authorization code.
state
OAuth 2.0 state value. REQUIRED if the state parameter is present in the Authorization Request from the TA. The TA MUST verify that the state value is equal to the exact value of state parameter in the Authorization Request.

7.1.5.2. Error Case - End-User Denied Authorization or Invalid Request

If the End-User denies the authorization or the End-User authentication fails, the Authorization Server MUST return the error authorization response as defined in 4.1.2.1 of OAuth 2.0 [RFC6749]. No other parameters SHOULD be returned.

7.1.6. Token Agent Obtains Primary ID Token, Access Token and Refresh Token

Once having obtained the code, the TA requests the corresponding primary tokens at the Token Endpoint as follows:

7.1.6.1. Token Agent Sends Code

The TA makes a request to the token endpoint as described in Section 4.1.3 of OAuth 2.0 [RFC6749].

The TA MUST authenticate to the Token Endpoint as described in Section 2.3 of OAuth 2.0 [RFC6749].

7.1.6.2. Token Agent Receives Tokens

The TA receives a response with the following parameters as described in Section 4.1.4 of OAuth 2.0 [RFC6749]. The response should be encoded using UTF-8.

access_token
REQUIRED. Primary Access Token for the AppInfo Endpoint.
token_type
REQUIRED. OAuth 2.0 token type value. The value MUST be "bearer". TA implementing this profile MUST support the OAuth 2.0 Bearer Token Usage [RFC6750] specification. This profile only describes the use of bearer tokens.
id_token
REQUIRED. Primary ID Token.
expires_in
OPTIONAL. Expiration time of the Access Token in seconds.
refresh_token
REQUIRED. Primary Refresh Token.

The following is a non-normative example (with line wraps for the display purposes only):

  HTTP/1.1 200 OK
  Content-Type: application/json
  Cache-Control: no-store
  Pragma: no-cache
  {
   "access_token":"SlAV32hkKG",
   "token_type":"bearer",
   "expires_in":3600,
   "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
   "id_token":"eyJ0 ... NiJ9.eyJ1c ... I6IjIifX0.DeWt4Qu ... ZXso"
  }

7.2. AppInfo Endpoint

To obtain application metadata information, the TA MAY make a GET or POST request to the AppInfo Endpoint.

AppInfo Endpoint Servers MUST require the use of a transport-layer security mechanism. The AppInfo Endpoint Server MUST support TLS 1.2 RFC 5246 [RFC5246] and/or TLS 1.0 [RFC2246] and MAY support other transport-layer mechanisms with equivalent security.

7.2.1. AppInfo Request

TA MAY send requests with the following parameters to the AppInfo Endpoint to obtain further information about the applications for which the TA can obtain secondary tokens. The AppInfo Endpoint is an OAuth 2.0 [RFC6749] Protected Resource that complies with the OAuth 2.0 Bearer Token Usage [RFC6750] specification. As such, the Access Token SHOULD be specified via the HTTP Authorization header.

access_token
REQUIRED. Access Token obtained from an OpenID Connect Authorization Request. This parameter MUST only be sent using one method through either the HTTP Authorization header or a form-encoded HTTP POST body parameter.
schema
REQUIRED. Schema in which the data is to be returned. The only defined schema value is napps.

7.2.2. AppInfo Response

The AS MUST determine the authorizations attached to the access_token sent by the TA and respond accordingly.

The AS MUST NOT include metadata for an application that the End-User is not authorized to use.

The top level JSON object contains a number of claims, that provide general configuration information for the TA. The top level elements are:

schema
OPTIONAL (String). The Schema version of response. The default if not specified is http:openid.net/schema/napps/1.0
branding
OPTIONAL (Object). Additional elements used to brand the TA interface.
apps
REQUIRED (Array). Zero or more JSON objects containing claims about applications that the TA can provide tokens or web boot-stap uri for.

Each object in the "apps" array describes a single application and may contain the following elements:

name
REQUIRED (String). The name to be displayed for the application in the TA UI.
type
REQUIRED (Array). An array of strings indicating the type of application. The defined types are "native" for applications requiring OAuth tokens, and "web" for applications that are invoked by the TA in a browser view.
scope
OPTIONAL (String). The value of "scope" is the identifier for the client application that is used in requests to the Token Endpoint as one of the space separated list of scopes when requesting access tokens for a native application. This is REQUIRED if the "type" is "native"
default_scopes
OPTIONAL (Array). This is an array containing the scope strings that the TA should request in addition to the value of "scope", if the client has not explicitly requested any scopes when requesting access tokens for a native application. This is RECOMMENDED if the "type" is "native"
icon_uri
OPTIONAL (String). This is is a link to an icon to display for the TA to display for the application.
web_init_ep
OPTIONAL (String). The value of this element is a URI for a OAuth 2 protected resource, that initiates web-sso by redirecting the requesting user agent via a HTTP redirect. This is REQUIRED if the "type" is "web"
bundle_id
OPTIONAL (String). This is a string that the TA uses to validate the identity of the invoking application. This is RECOMMENDED if the "type" is "native"
custom_uri
OPTIONAL (String). This is a string that contains a custom scheme URI that TA uses to return responses to the application. In environments that support URI based inter application communication, this is the base URI that MUST be used for returning responses. Custom scheme URI can be impersonated by malicious applications. This should not be used as the only confirmation of the client application's identity. (Note the format of the URI value will be different between iOS and Android, this needs to be covered in the API spec) This is RECOMMENDED if the "type" is "native"

The AS returns the application metadata information to the TA in the form of a JSON object, an example of which is shown below

{
    "schema": "http:openid.net/schema/napps/1.0",
    "branding": {
        "companyname": "ABS",
        "companyiconurl": "http://www.ABS.com/logo.gif"
    },
    "apps": [
            {
                "name": "Boxx",
                "type": "native",
                "scope": "urn:oauth:boxx",
                "default_scopes": ["read" , "admin" ],
                "icon_uri": "http://www.example.com/pic.png",
                "custom_uri": "app1://callback-uri/"
            },
            {
                "name": "test1",
                "type": "web",
                "scope": "urn:oauth:test1",
                "default_scopes": ["urn:oauth:web-sso"],
                "icon_uri": "http://www.example.com/pic.png",
                "web_init_ep": "http://init-sso.example.com/start"
        ]

}

The TA MAY use the information from the AppInfo endpoint to build a user interface for the user, displaying the applications they are authorized to use.

The TA MUST use the value of the scope parameter to indicate the desired targeted application when subsequently requesting a secondary access token for that application.

If using the custom URL scheme mechanism to pass the secondary access token to the relevant application, the TA MUST use the value of the customurl parameter when constructing the URL.

7.3. Requesting a Initiate SSO Access Token

The TA may request a access token to invoke Web SSO by making a request to the AS token_endpoint and including the scope "urn:oauth:init-sso"

If the application is permitted to request tokens to access multiple Web resources, It may also send the "aud" paramater containing a string with the uri of the target resource"

7.4. Initiate SSO Endpoint

The Initiate SSO Endpoint is a OAuth 2 protected endpoint that is used to bootstrap Web Single Sign-on for a browser user agent.

Initiate SSO Endpoint Servers MUST require the use of a transport-layer security mechanism. The Initiate SSO Endpoint Server MUST support TLS 1.2 RFC 5246 [RFC5246] and/or TLS 1.0 [RFC2246] and MAY support other transport-layer mechanisms with equivalent security.

7.4.1. Init SSO Request

TA MAY send requests with the following parameters to the Initiate SSO Endpoint by invoking a web view, or by passing them to a requesting native app that will invoke them in a web view. The Initiate SSO Endpoint is an OAuth 2.0 [RFC6749] Protected Resource that complies with the OAuth 2.0 Bearer Token Usage [RFC6750] specification. As such, the Access Token SHOULD be specified via the HTTP Authorization header.

access_token
REQUIRED. Access Token obtained from an OpenID Connect Authorization Request. This parameter MUST only be sent using one method through either the HTTP Authorization header or a form-encoded HTTP POST body parameter.

7.4.2. InitSSO Response

The response is a HTTP 3xx redirect containing a IdP initiated authorization response in the Location: header.

7.5. Primary access token refresh

The TA MAY use its primary refresh token to obtain fresh primary access tokens for its own use on calls to the AppInfo endpoint.

If the TA does not specify a scope of any native application on its refresh call, it is requesting a fresh primary access token.

The TA MUST NOT share its primary access or refresh tokens with other native applications.

7.6. Secondary Access Token Retrieval

The TA can use its primary refresh token to obtain secondary access tokens for native applications. Depending on the requirements of the targeted application, a secondary access token is either directly returned for the refresh token, or an id_token that csn be subsequently exchanged at an AS hosted by the application provider. The second scenario supports deployments where some native applications are already associated withnan AS, and the application RS is preconfigured to only validate tokens against that AS.

The TA can be prompted to obtain an secondary access token for an application either due to a user clicking on an icon displayed by the TA (a launcher model) , or by the native application asking the TA for a token (presumably after being launched through the OS native UI).

7.6.1. Secondary access token request

The TA MUST use its primary refresh token to request of the AS a secondary access token - specifying as a scope the relevant native application to be targeted (rather than itself). The TA MAY obtain the relevant scope parameter for a particular native application via the AppInfo endpoint or through some other mechanism.

Example of a refresh call where the TA is asking for a secondary access token for a native application with a specified scope of urn:oauth:boxx.

POST /as/token.oauth2 HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

grant_type=refresh_token&
  refresh_token=qANLTbu17rk17lPszecHRi7rqJt46pG1qx0nTAqXWH&
  scope=urn:oauth:boxx

7.6.2. Response

The AS MUST verify that the End-User is authorized to use the particular native application for which the secondary access token was requested.

The AS MAY check local policy, or MAY call out to an external policy store.

If authorized, the AS returns the secondary access token or id_token, depending on the policy configured for that application.

The AS MAY bind the secondary access token to the specific native application through cryptographic or other means.

7.6.3. Secondary access token retrieval from remote AS

TBD - show how the TA 1) obtains an id_token using the refresh token and 2) uses that id_token to request of a secondary AS an access token.

7.7. Validation

When an RS receives a secondary access token on an API call from a native application, it will need to validate that access token to determine whether to approve the request or not.

This profile does not dictate a particular validation model.

Depending on the nature of the secondary access token, the RS MAY call back to the issuing AS for validation. Alternatively the RS MAY validate the token *locally*, ie through verification of a signature over that token.

8. Native Application Interactions

The Bindings specification [NAPPS.Bindings] outlines how a TA might pass secondary access tokens to corresponding native applications, or how the native application might request of the TA such a secondary access token.

9. Security Considerations

TBD

10. Privacy Considerations

TBD

11. IANA Considerations

This document makes no requests of IANA.

12. Normative References

[JWT] Jones, M., Bradley, J. and N. Sakimura, "JSON Web Token (JWT)", Internet-Draft draft-ietf-oauth-json-web-token, May 2013.
[NAPPS.Bindings] Madsen, P., Jain, A., Zmolek, A. and T. Bradley, "OpenID Connect Native Application Token Agent API Bindings 1.0", January 2014.
[OpenID.Core] Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., Mortimore, C. and E. Jay, "OpenID Connect Standard 1.0", December 2013.
[OpenID.Registration] Sakimura, N., Bradley, J. and M. Jones, "OpenID Connect Dynamic Client Registration 1.0", December 2013.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997.
[RFC2246] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0", RFC 2246, DOI 10.17487/RFC2246, January 1999.
[RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008.
[RFC6749] Hardt, D., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, October 2012.
[RFC6750] Jones, M. and D. Hardt, "The OAuth 2.0 Authorization Framework: Bearer Token Usage", RFC 6750, DOI 10.17487/RFC6750, October 2012.
[RFC7519] Jones, M., Bradley, J. and N. Sakimura, "JSON Web Token (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015.

Appendix A. Acknowledgements

The following have contributed to the development of this specification.

Appendix B. Notices

Copyright (c) 2014 The OpenID Foundation.

The OpenID Foundation (OIDF) grants to any Contributor, developer, implementer, or other interested party a non-exclusive, royalty free, worldwide copyright license to reproduce, prepare derivative works from, distribute, perform and display, this Implementers Draft or Final Specification solely for the purposes of (i) developing specifications, and (ii) implementing Implementers Drafts and Final Specifications based on such documents, provided that attribution be made to the OIDF as the source of the material, but that such attribution does not indicate an endorsement by the OIDF.

The technology described in this specification was made available from contributions from various sources, including members of the OpenID Foundation and others. Although the OpenID Foundation has taken steps to help ensure that the technology is available for distribution, it takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this specification or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any independent effort to identify any such rights. The OpenID Foundation and the contributors to this specification make no (and hereby expressly disclaim any) warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to this specification, and the entire risk as to implementing this specification is assumed by the implementer. The OpenID Intellectual Property Rights policy requires contributors to offer a patent promise not to assert certain patent claims against other contributors and against implementers. The OpenID Foundation invites any interested party to bring to its attention any copyrights, patents, patent applications, or other proprietary rights that may cover technology that may be required to practice this specification.

Appendix C. Document History

[[ To be removed from the final specification ]]

-01

-02

-03

Authors' Addresses

Paul Madsen Ping Identity EMail: paul.madsen@gmail.com
Ashish Jain VMware EMail: itickr@gmail.com
Andy Zmolek Google EMail: zmolek@google.com
John Bradley Ping Identity EMail: jbradley@pingidentity.com