While Authorization code flow is commonly used for webserver applications, for native apps and spa (without back end) authorization code flow with PKCE (Proof key for code exchange) is used as mobile apps without backend cannot keep the client secret confidential. In case of native app simply decompiling the app will reveal the Client Secret and in case of spa the entire source is available to the browser.

The PKCE flow does not require client secret. Note that the implicit grant flow for native apps is now deprecated. In the implicit grant flow, the access token was directly issued by authorization end point. As the access token was part of redirect url, hence the implicit grant flow is not safe and is replaced by authorization code flow with pkce .(client secret is replaced by one time/one request secret) The right way for authorizing users in native apps is to perform the OAuth authorization request in an external user-agent (typically the browser).

Embedded user-agent (such as web-views) should be avoided as

Just as URIs are used for OAuth 2.0 on the web to initiate the authorization request and return the authorization response to the requesting website, Interapp URIs can be used by native apps to initiate the authorization request in the device's browser and return the response to the requesting native app.

Mobile platforms support inter-app communication via URIs by allowing apps to register private-use URI schemes (also called custom URL schemes). To perform an OAuth 2.0 authorization request with a private-use URI scheme redirect, the native app launches the browser with a standard authorization request. When the authentication server completes the request, it redirects to the client's redirection URI . As the redirection URI uses a custom scheme it results in the operating system launching the native app, passing in the URI as a launch parameter. The native app then processes the authorization response like normal.

A malicious app can register and receive redirects with the authorization code for legitimate apps. This is known as an Authorization Code Interception Attack. In the PKCE flow the legitimate app which generated the code challenge would know the code verifier and would be able to exchange auth code with tokens. Malicious app can get the auth code but would not be able to exchange it with tokens as it would not know the codeverifier. It should be noted that malicious app cannot extract client secret from genuine app as client secret does not exist in pkce flow. Also the code verifier is hidden as in the initial authorization request, code challenge is sent, which is hashed code verifier, hence code verfier will not be visible in browser history. 

Steps in brief

pkce

Request to authorization end point

https://auth-server.com/authorize?response_type=code& client_id=CLIENT_ID&redirect_uri=myapp://callback&scope=photos&state=stxyxze

The client app opens a browser tab, directing the user to the /authorize endpoint of the authserver. The request parameters are

When the authorization request reaches the authorization server the auth server will

authorize

If the user allows then the authorization service will redirect the user to redirect uri with auth code.

Response from authorization end point

myapp://callback?code=AUTH_CODE&state=stxyxze

This is redirect to private / custom uri and will lead to launch of the native app.

On receiving the redirect response  the native app will

POST request to token end point

https://api.authorization-server.com/token?grant_type=authorization_code&code=AUTH_CODE&redirect_uri=REDIRECT_URI&client_id=CLIENT_ID& code_verifier=code verifier string

The native app will initiate a POST request to token end point to get access and/or id token with

The token end point responds with access token and / or id token

web controller components for native apps

Both Apple (iOS9+ - SFSafariViewController) and Google (Chrome 45+ - Chrome Custom Tabs) have added a web controller that provides all the benefits of the native system browser in a control that can be placed within an application. Most importantly you get cookie based single sign on capability (unlike webviews cookies will persist when using web controller components as cookies are shared across instances) . besides you would get user experience like webviews , ie the user stays within the application. also web controller are secure like browser as application does not have access to browser data.

Attacks (CSRF/REPLAY/Authorization code interception attack)