Building JavaScript and mobile/native Clients for Token ... · •Cookies are the typical approach...

Post on 29-Jun-2020

3 views 0 download

Transcript of Building JavaScript and mobile/native Clients for Token ... · •Cookies are the typical approach...

Building JavaScript and mobile/native Clients for

Token-based Architectures

identity@leastprivilege.com

@brocklallen & @leastprivilege

https://identityserver.io

Brock Allen & Dominick Baier

2@leastprivilege / @brocklallen

The big Picture

Browser

Native App

Server App"Thing"

Web App

Web API Web API

Web API

Security Token Service

3@leastprivilege / @brocklallen

Security Protocols (I)

Browser

Native App

Server App"Thing"

Web App

Web API Web API

Web API

OpenID Connect*

Security Token Service

*

*

4@leastprivilege / @brocklallen

Security Protocols (II)

Browser

Native App

Server App"Thing"

Web App

Web API Web API

Web API

OAuth 2.0

OAuth 2.0

OAuth 2.0

OAuth 2.0

OAuth 2.0

OAuth 2.0

Security Token Service

*

*

OpenID Connect*

5@leastprivilege / @brocklallen

Clients

Browser

Native App

Web API

OAuth 2.0

OAuth 2.0

Security Token ServiceOpenID Connect

OpenID Connect

6@leastprivilege / @brocklallen

Token-based Clients…

Clients

Web API

Security Token Service

Users

(1) Authenticate,establish session

(2) identity token,access token

(3) process response,validate identity token

(4) use access token

7@leastprivilege / @brocklallen

Local Logon UI vs Redirect/Server-rendered

UsernamePassword

Login

8@leastprivilege / @brocklallen

Modern/Pure JavaScript apps

• Client

– Browser-based

– Entirely JavaScript (SPA)

– Dynamic rendering all client side

• Sever• Thin server

• Static content (HTML, JS, CSS, etc.)

• Ajax endpoints (HTTP APIs)

9@leastprivilege / @brocklallen

No more cookies for security

• Cookies are the typical approach for server-side applications

– But not appropriate for modern JavaScript apps

• Modern apps don't have/use server-side HTML framework

– SPAs (or mobile apps) are doing the UI client-side

• APIs can't use cookies

– API might be cross-domain

– Cookies don't make sense for non-browser clients

– Cross-site request forgery (XSRF) security issues

10@leastprivilege / @brocklallen

Discovery

https://authority

{"issuer": "https://authority","jwks_uri": "https://authority/.well-known/jwks",

"authorization_endpoint": "https://authority/authorize","token_endpoint": "https://authority/token","userinfo_endpoint": "https://authority/userinfo",

"frontchannel_logout_supported": true,"scopes_supported": [ "openid", "profile", "email", "address", "phone", "offline_access", "api" ],"grant_types_supported": [ "authorization_code", "client_credentials", "password", "refresh_token", "implicit" ],

}

/.well-known/openid-configuration

11@leastprivilege / @brocklallen

Authentication in JS-based apps

• OpenId Provider (OP)

– Issues tokens

• 1) Client makes request to OP

– User authenticates

– User consents (optional)

• 2) OP returns to client

– Accept id token

– Client validates id token

bob

secret

id_token

12@leastprivilege / @brocklallen

Id tokens• Format is JSON web token (JWT)

eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMD.4MTkzODAsDQogImh0dHA6Ly9leGFt

Header Claims Signature

{"typ": "JWT","alg": "RS256","kid": "mj399j…"

}

{"iss": "https://idsrv3","exp": 1340819380,"aud": "app1","nonce": "289347898934823",

"sub": "182jmm199","email": "alice@alice.com","email_verified": true,"amr": "password","auth_time": 12340819300

}

13@leastprivilege / @brocklallen

Validating id tokens

• Steps to validate:

1. Base64Url decode id_token and parse into JSON (formatting step)

2. Verify nonce is same as sent in request (prevents XSRF/replay)

3. Validate signature on token (establishes trust [requires crypto])

4. Validate iss same as issuer of OIDC OP (establishes trust)

5. Validate aud same as this client's identifier (prevents privilege escalation)

6. Validate exp is still valid (prevents stale tokens)

14@leastprivilege / @brocklallen

oidc-client

• JavaScript helper class that implements OIDC protocol

– Includes id_token validation

• Including crypto implementation

– Heavy use of promises

• http://github.com/IdentityModel/oidc-client-js– Also available via npm

15@leastprivilege / @brocklallen

More identity data

• Might need more than sub (subject) claim

• scope used to ask for more identity data

16@leastprivilege / @brocklallen

More identity data with user profile

• Id token might become too large

– Needs to fit into URL

• OIDC defines user info endpoint

– Ajax call to load user profile

– Requires authorization with an access token obtained in OIDC request

17@leastprivilege / @brocklallen

Requesting access token

• Add "token" to response_typeparameter to authorization endpoint

• More validation required (same as before, plus):

– Hash access token and compare left half to at_hash in id token (ensures id token is paired with access token)

id_tokenaccess_token

access_token

user profile

id_tokentoken

18@leastprivilege / @brocklallen

Using access token to call user profile

• Access token passed as Authorization HTTP request header

• Response is JSON of user profile based upon requested scopes

var xhr = new XMLHttpRequest();xhr.onload = function () {

var user_profile = JSON.parse(xhr.response);}

xhr.open("GET", user_profile_endpoint);xhr.setRequestHeader("Authorization", "Bearer " + access_token);xhr.send();

19@leastprivilege / @brocklallen

Calling other web APIs

• APIs use access token from same OIDC OP

• Just need to request more scopes

access_token

access_token

JSON

scope: api1

20@leastprivilege / @brocklallen

Logout

• Throw away tokens in client

• Signing out of OIDC OP

– Must make request to OP

• Post logout redirect

– Must pass redirect URL as post_logout_redirect_uri

– Must pass original id token as id_token_hint

21@leastprivilege / @brocklallen

Token management

• Token storage

– localStorage

– sessionStorage

– indexedDb

• Token expiration

– Access tokens expire (1h, 10h, 1d, 30d, whatever)

– Need a way to manage this lifetime

• Wait for 401 from API

• Renew prior to expiration

22@leastprivilege / @brocklallen

Renewing tokens

• Request new token in a hidden iframe

– only possible if no user interaction is required

JS app

iframe /authorize?...&prompt=none

23@leastprivilege / @brocklallen

Native Clients

• Applications that have access to native platform APIs

– desktop or mobile

– more options / features

• OAuth 2.0 / OpenID Connect for native applications

– https://tools.ietf.org/wg/oauth/draft-ietf-oauth-native-apps/

24@leastprivilege / @brocklallen

Using a web server for driving the authentication workflow

authentication request

render UI & workflow

25@leastprivilege / @brocklallen

Browser types

• Embedded web view

– private browser & private cookie container

– e.g. WinForms or WPF browser control

• Authentication broker

– "special" browsers (look private but share some cookies)

– e.g. Win8 & UWP WebAuthenticationBroker

• In-app browser tab / system browser

– full blown system browser (including address bar & add-ins)

– shared cookie container

– e.g. SafariViewController (iOS9) & Chrome Custom Tabs (Android 5)

26@leastprivilege / @brocklallen

OpenID Connect Hybrid Flow

GET /authorize

?client_id=nativeapp&scope=openid profile api1 api2 offline_access&redirect_uri=com.mycompany.nativeapp://cb&response_type=code id_token&nonce=j1y…a23&code_challenge=x929..1921

nonce = random_numbercode_verifier = random_numbercode_challenge = hash(code_verifier)

27@leastprivilege / @brocklallen

Receiving the response

GET com.mycompany.nativeapp://cb

#id_token=x12f…zsz&code=818…1299

callback

28@leastprivilege / @brocklallen

Validating the response

• Identity token validation (section 3.1.3.7)

– validate signature

• key material available via discovery endpoint

– validate iss claim

– validate exp (and nbf)

– validate aud claim

• Authorization code validation (section 3.3.2.10)

– hash authorization code and compare with c_hash claim

https://openid.net/specs/openid-connect-core-1_0.html

29@leastprivilege / @brocklallen

Requesting the access token

• Exchange code for access token

– using client id and secret

code & code verifier

(client_id)

{access_token: "xyz…123",refresh_token: "dxy…103",id_token: "xyz…123",expires_in: 3600,token_type: "Bearer"

}

30@leastprivilege / @brocklallen

Next steps

• Persist the data in protected storage

– claims

– access token

– refresh token

• Use access token to communicate with APIs

• Use refresh token to get new access tokens when necessary

31@leastprivilege / @brocklallen

Refreshing an Access Token

refresh_token

(client_id)

{access_token: "xyz…123",refresh_token: "jdj9…192j",expires_in: 3600,token_type: "Bearer"

}

32@leastprivilege / @brocklallen

Libaries

• C# portable class library

– desktop .NET, UWP, Xamarin iOS & Android

• https://github.com/IdentityModel/IdentityModel.OidcClient

• C# NetStandard 1.4 library (WIP)

– desktop .NET, .NET Core, Xamarin iOS & Android

• Native libraries

– https://github.com/openid/AppAuth-iOS

– https://github.com/openid/AppAuth-Android

33@leastprivilege / @brocklallen

thank you!get slides from https://speakerdeck.com/leastprivilege