Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add docs for native sign in using Apple SDK #1528

Merged
merged 3 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { FrontendApi } from "@ory/client"
import * as AppleAuthentication from "expo-apple-authentication"
import * as Crypto from "expo-crypto"

async function signInWithApplePayload(): Promise<{
id_token: string
id_token_nonce: string
traits: Record<string, unknown>
}> {
const digest = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
Crypto.getRandomBytes(16).toString(),
)
let credential: AppleAuthentication.AppleAuthenticationCredential
try {
credential = await AppleAuthentication.signInAsync({
requestedScopes: [
AppleAuthentication.AppleAuthenticationScope.EMAIL,
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
],
nonce: digest,
})
} catch (e) {
console.error("Couldn't sign in with Apple: ", e)
throw e
}

return {
id_token: credential.identityToken || "",
id_token_nonce: digest,
traits: {
name: {
first: credential.fullName?.givenName || "given name",
last: credential.fullName?.familyName || "last name",
},
},
}
}

export async function signInWithApple(sdk: FrontendApi, flowId: string) {
const payload = await signInWithApplePayload()
return sdk.updateLoginFlow({
flow: flowId,
updateLoginFlowBody: {
method: "oidc",
provider: "apple",
...payload,
},
})
}

export async function registerWithApple(sdk: FrontendApi, flowId: string) {
const payload = await signInWithApplePayload()
return sdk.updateRegistrationFlow({
flow: flowId,
updateRegistrationFlowBody: {
method: "oidc",
provider: "apple",
...payload,
},
})
}
36 changes: 36 additions & 0 deletions docs/kratos/social-signin/30_apple.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,42 @@ Follow these steps to add Apple as a social sign-in provider to your project usi
</Tabs>
````

## Using the Apple SDK on native apps

Apple provides a more integrated UX for native apps using the
[Apple SDK](https://developer.apple.com/documentation/sign_in_with_apple/implementing_user_authentication_with_sign_in_with_apple).
This flow uses the native Apple SDK and does not require a browser. This results in a signed `id_token` on the client side which
is exchanged at Ory for a session token.

The following steps are required to integrate the Apple SDK with Ory:

1. Configure an Apple social sign-in provider in Ory using the same `client_id` as in your native app.
2. Generate a random value that you can use as a `nonce`.
3. Obtain an `id_token` from Apple using the Apple SDK. Make sure to also submit the `nonce`.
4. Submit the `id_token` and `nonce` (as the `id_token_nonce`) as part of the `updateRegistrationFlow` or `updateLoginFlow`
request to Ory.
5. Ory will validate the `id_token` and create an identity and optionally a session (if configured).

The `id_token` is verified using Apple's publicly available signing keys, available under https://appleid.apple.com/auth/keys.
jonas-jonas marked this conversation as resolved.
Show resolved Hide resolved

The `id_token` issued by Apple only contains the user's email address. You can submit additional claims to Ory as part of the
`updateRegistrationFlow` request, as `traits`.

:::warning

As Ory does not communicate directly with Apple during this flow, it does not have access to the Access & Refresh Tokens. This
means that Ory cannot return these in the admin APIs or SDK. If you need these tokens, you can exchange the `authorization_code`
returned by Apple on the device manually.

:::

```mdx-code-block
import CodeBlock from '@theme/CodeBlock'
import revokeOtherSessionsReact from "!!raw-loader!@site/code-examples/sdk/typescript/src/selfservice/registration/apple-social-sign-in-native.ts"

<CodeBlock language="ts" title="apple-social-sign-in-react-native.tsx">{revokeOtherSessionsReact}</CodeBlock>
```

## Troubleshooting

```mdx-code-block
Expand Down
9 changes: 8 additions & 1 deletion docs/kratos/social-signin/96_native-apps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ this:
- The user authenticates with the identity provider and grants the application access to profile information.
- The user is redirected back to the application and is logged in.

:::note

Apple supports a more tightly integrated login experience for native apps. See the documentation on
[Apple social sign-in](./apple#using-the-apple-sdk-on-native-apps) for more information.

:::

## The native app authentication flow

From a high level, the native app initializes a login or registration flow and receives the first part of the session token
Expand All @@ -32,7 +39,7 @@ exchange code for a session token.
:::info

As part of this flow, Ory will redirect the browser to a callback. In this demo, we use the redirect URL
`http://localhost:4457/Callback`. Please ensure that this
`http://localhost:19006/Callback`. Please ensure that this
[redirect URL is allowed](https://console.ory.sh/projects/current/browser-redirects)!

:::
Expand Down
Loading