Slide 1

Slide 1 text

Authentication & API Access for native/mobile Applications Dominick Baier dominick.baier@leastprivilege.com http://leastprivilege.com @leastprivilege

Slide 2

Slide 2 text

2 @leastprivilege Dominick Baier • Independent Consultant – Specializing on Identity & Access Control – Working with Software Development Teams (ISVs and in-house) • Creator and Maintainer of IdentityServer/IdentityModel OSS Projects – OpenID Connect & OAuth 2.0 Implementation for ASP.NET / Core – .NET Foundation Advisory Board – http://identityserver.io dominick.baier@leastprivilege.com http://leastprivilege.com slides: https://speakerdeck.com/leastprivilege

Slide 3

Slide 3 text

3 @leastprivilege tl;dr • Implementing authentication and API access for native/mobile applications – IOW applications that have access to native platform APIs – desktop or mobile • Following the guidance of "OAuth 2.0 for native Applications" – https://tools.ietf.org/html/draft-wdenniss-oauth-native-apps-02

Slide 4

Slide 4 text

4 @leastprivilege The big picture Browser Native App Server App "Thing" Web App Web API Web API Web API Security Token Service

Slide 5

Slide 5 text

5 @leastprivilege Security protocols (I) Browser Native App Server App "Thing" Web App Web API Web API Web API OpenID Connect Security Token Service OpenID Connect OpenID Connect

Slide 6

Slide 6 text

6 @leastprivilege 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 OpenID Connect OpenID Connect

Slide 7

Slide 7 text

7 @leastprivilege So many options… • Low hanging fruit – OAuth 2.0 resource owner password credential flow • Better, but is missing out on some advanced features – OAuth 2.0 implicit flow • Recommended – OAuth 2.0 authorization code flow (with PKCE) • …and my favourite – OpenID Connect Hybrid Flow (with PKCE)

Slide 8

Slide 8 text

8 @leastprivilege Native login dialogs Username Password Login username/password token token trust Token service API

Slide 9

Slide 9 text

9 @leastprivilege OAuth 2.0 Resource Owner Password Flow • Pros – client app has full control over login UI – support for long lived API access without having to store a password • Cons – user is encouraged to type in his master secret into "external" applications • especially problematic once applications also come from 3rd parties – no cross application single sign-on or shared logon sessions – no federation with external identity providers/business partners – every change in logon workflow requires versioning the application

Slide 10

Slide 10 text

10 @leastprivilege Using a browser for driving the authentication workflow authentication request render UI & workflow

Slide 11

Slide 11 text

11 @leastprivilege Using a browser for driving the authentication workflow • Centralize authentication logic – consistent look and feel – implement once, all applications get it for free – allows changing the workflow without having to update the applications • e.g. consent, updated EULA, 2FA • Enable external identity providers and federation – federation protocols are browser based only • Depending on browser, authentication sessions can be shared between apps and OS

Slide 12

Slide 12 text

12 @leastprivilege 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 – full blown system browser (including address bar & add-ins) – shared cookie container – e.g. SafariViewController(iOS9) & Chrome Custom Tabs (Android 5)

Slide 13

Slide 13 text

13 @leastprivilege How to implement? • Implicit flow – really designed for JS apps – access tokens transmitted over browser (and potentially cross process) – no refresh tokens • Authorization code-based flows – access tokens only over back-channel communication – slightly more secure due to client secret – allows long lived API access via refresh tokens – authorization code itself needs to be protected though • cut'n paste attack • man in the middle

Slide 14

Slide 14 text

14 @leastprivilege Starting the authentication request 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_number code_verifier = random_number code_challenge = hash(code_verifier)

Slide 15

Slide 15 text

15 @leastprivilege Receiving the response GET com.mycompany.nativeapp://cb #id_token=x12f…zsz &code=818…1299 callback

Slide 16

Slide 16 text

16 @leastprivilege Identity token { "typ": "JWT", "alg": "RS256", "kid": "mj399j…" } { "iss": "https://idsrv", "exp": 1340819380, "aud": "nativeapp", "nonce": "j1y…a23", "amr": [ "password", "sms" ], "auth_time": 12340819300 "sub": "182jmm199" } Header Payload eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMD.4MTkzODAsDQogImh0dHA6Ly9leGFt Header Payload Signature base64url

Slide 17

Slide 17 text

17 @leastprivilege 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

Slide 18

Slide 18 text

18 @leastprivilege Requesting the access token • Exchange code for access token – using client id and secret code & code verifier (client_id:client_secret) { access_token: "xyz…123", refresh_token: "dxy…103" expires_in: 3600, token_type: "Bearer" }

Slide 19

Slide 19 text

19 @leastprivilege Optional: download more claims • OpenID Connect UserInfo endpoint provides claims as JSON object access token { "given_name": "Kendall", "preferred_username": "FluffyBunnySlippers" "profile_picture": " " }

Slide 20

Slide 20 text

20 @leastprivilege 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

Slide 21

Slide 21 text

21 @leastprivilege That's a lot of work! • Native libraries – https://github.com/openid/AppAuth-iOS – https://github.com/openid/AppAuth-Android • C# portable class library (desktop .NET, UWP, mobile, iOS, Android) – https://github.com/IdentityModel/IdentityModel.OidcClient – https://github.com/IdentityModel/IdentityModel.OidcClient.Samples

Slide 22

Slide 22 text

22 @leastprivilege OSS FTW! IdentityModel.OidcClient - OidcClient - Browser coordination - Discovery document support IdentityModel Jose-Pcl PCLCrypto - JWT validation - JWK handling - voodoo - OpenID Connect & OAuth 2.0 protocol - Refresh token handling

Slide 23

Slide 23 text

23 @leastprivilege Setup var options = new OidcClientOptions( authority: authority, clientId: "native", clientSecret: "secret", scope: "openid profile api offline_access", redirectUri: "com.mycompany.myapp://callback", webView: webView); var client = new OidcClient(options);

Slide 24

Slide 24 text

24 @leastprivilege Authentication & requesting tokens var result = await client.LoginAsync(); var claims = result.Claims; var accessToken = result.AccessToken; var refreshToken = result.RefreshToken;

Slide 25

Slide 25 text

25 @leastprivilege Calling APIs and keeping tokens fresh var apiClient = new HttpClient(result.Handler); apiClient.BaseAddress = new Uri("https://www.mycompany.com/api/"); var tokenClient = new TokenClient( address: "https://demo.identityserver.io/connect/token", clientId: "client", clientSecret: "secret"); var handler = new RefeshTokenHandler(tokenClient, refreshToken); or…

Slide 26

Slide 26 text

26 @leastprivilege Stepping up security: bearer vs pop tokens

Slide 27

Slide 27 text

27 @leastprivilege Adding a proof key & signature 1) client generates pub/priv key pair 2) sends public key to STS during token request 4) client uses private key to sign HTTP request 3) STS embeds pub key in access token 5) API validates access token 6) extracts proof key & validates the HTTP signature pub key token incl. pub key token incl. pub key signature

Slide 28

Slide 28 text

28 @leastprivilege That's even more work!!! • Helper libraries – https://github.com/IdentityModel/IdentityModel.Owin.PopAuthentication – https://github.com/IdentityModel/IdentityModel.HttpSigning • The specs (not done yet) – https://tools.ietf.org/wg/oauth/draft-ietf-oauth-pop-architecture/ – https://tools.ietf.org/wg/oauth/draft-ietf-oauth-token-exchange/ – https://tools.ietf.org/wg/oauth/draft-ietf-oauth-signed-http-request/

Slide 29

Slide 29 text

29 @leastprivilege Summary • NAPPS spec recommends code based authentication flow – with PKCE – id_token adds signed response and signature over authorization code • Use system level browser for best user experience – shared logon sessions – password managers • Use refresh tokens for long lived API access – store them securely • Look into PoP for further protection against man-in-the-middle

Slide 30

Slide 30 text

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