For an application developer, the application flow is similar to the typical client-server flow used by centralized sign in services (e.g., OAuth). However, with Blockstack, the authentication flow happens entirely client-side.
A decentralized application and [the Blockstack App](https://github.com/blockstack/ux/tree/master/packages/app) communicate during the authentication flow by passing back and forth two tokens. The requesting application sends the Blockstack App an `authRequest` token. Once a user approves a sign-in, the Blockstack App responds to the application with an `authResponse` token. These tokens are <ahref="https://jwt.io/"target="\_blank">JSON Web Tokens</a>, and they are passed via URL query strings.
When a user chooses to authenticate a decentralized application, it calls the `doOpenAuth()` method which sends an `authRequest` to the Blockstack App. Blockstack passes the token in via a URL query string in the `authRequest` parameter:
When the Blockstack App receives the request, it generates an (`authResponse`) token to the application using an _ephemeral transit key_ . The ephemeral transit key is just used for the particular instance of the application, in this case, to sign the `authRequest`. The application stores the ephemeral transit key during the request generation. The public portion of the transit key is passed in the `authRequest` token. The Blockstack App uses the public portion of the key to encrypt an _app-private key_ which is returned via the `authResponse`.
During sign in, the Blockstack App generates the app-private key from the user's _identity-address private_ key and the application's `appDomain`. The app private key serves three functions: