diff --git a/code-examples/sdk/dart/social-sign-in/sign-in-with-google.dart b/code-examples/sdk/dart/social-sign-in/sign-in-with-google.dart new file mode 100644 index 000000000..4fa9342e5 --- /dev/null +++ b/code-examples/sdk/dart/social-sign-in/sign-in-with-google.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +import 'package:google_sign_in/google_sign_in.dart'; +import 'package:one_of/one_of.dart'; +import 'package:ory_client/ory_client.dart'; + +class SignInWithGoogleButton extends StatelessWidget { + final String flowId; + final OryClient ory; + + // highlight-start + final GoogleSignIn _googleSignIn = GoogleSignIn( + scopes: [ + 'email', + // Add additional scopes, if you require that data in your Jsonnet mapping + ], + ); + // highlight-end + + SignInWithGoogleButton({super.key, required this.flowId, required this.ory}); + + // highlight-start + void handleGoogleSignIn(GoogleSignInAccount? value) { + value?.authentication.then((value) { + var idToken = value.idToken; + if (idToken == null) { + // If we end up here, but there is no ID token, something went wrong + print("No idToken found"); + return; + } + + // Create the payload for the updateRegistrationFlow endpoint with the idToken from Google + var body = UpdateRegistrationFlowWithOidcMethod( + (b) => b + ..idToken = idToken + ..method = 'oidc' + ..provider = 'google', + ); + + // Submit the updateRegistrationFlow endpoint with the payload + ory.getFrontendApi().updateRegistrationFlow( + flow: flowId, + updateRegistrationFlowBody: UpdateRegistrationFlowBody( + (b) => b..oneOf = OneOf.fromValue1(value: body)), + ); + }); + } + // highlight-end + + @override + Widget build(BuildContext context) { + return TextButton( + child: const Text("Sign in with Google"), + onPressed: () => {_googleSignIn.signIn().then(handleGoogleSignIn)}, + ); + } +} diff --git a/docs/kratos/social-signin/10_google.mdx b/docs/kratos/social-signin/10_google.mdx index 507396131..1a52b8dec 100644 --- a/docs/kratos/social-signin/10_google.mdx +++ b/docs/kratos/social-signin/10_google.mdx @@ -234,6 +234,54 @@ The parameters can be passed along to Ory on `login`, `registration` and `settin See the [Advanced Integration](../bring-your-own-ui/custom-ui-advanced-integration#upstream-provider-parameters) document for more information on passing parameters from your UI to Ory. +## Using the Google SDK on native apps + +Google provides a more integrated UX for native apps using the +[Google SDK](https://developers.google.com/identity/sign-in/web/backend-auth). This flow uses the native Google SDK and does not +require a browser. This results in a signed `id_token` on the client side (typically your app) which is exchanged at Ory for a +session token. + +The following steps are required to integrate the Google SDK with Ory: + +1. Configure a Google social sign-in provider in Ory using the same `client_id` as used in your native app. +2. If your SDK supports nonce validation, make sure to use a generated value and submit that during the next step. +3. Obtain an `id_token` from Google using the Google SDK. Make sure to also submit the `nonce` if you generated one in the step + before. +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 Google's publicly available signing keys, available under +https://www.googleapis.com/oauth2/v3/certs. + +Make sure to request the scopes you require in your Jsonnet mapping, otherwise they will be empty after the registration. + +:::warning + +While not explicitly required, as not all of Google SDKs support it, we recommend that you use a `nonce` to prevent replay attacks +wherever possible. + +::: + +:::info + +Ory does not communicate directly with Google during this flow and does not have access to the Access & Refresh Tokens. This means +that Ory cannot return these in the admin APIs or SDK. + +::: + +### Flutter code example + +The following showcases an example implementation of a Sign in with Google button using the Ory SDK and +[google_sign_in](https://pub.dev/packages/google_sign_in) Flutter package. + +```mdx-code-block +import CodeBlock from '@theme/CodeBlock' +import signInWithGoogleSnippet from "!!raw-loader!@site/code-examples/sdk/dart/social-sign-in/sign-in-with-google.dart" + +{signInWithGoogleSnippet} +``` + ## Troubleshooting ```mdx-code-block diff --git a/docs/kratos/social-signin/30_apple.mdx b/docs/kratos/social-signin/30_apple.mdx index 895bfd876..6317f6d5e 100644 --- a/docs/kratos/social-signin/30_apple.mdx +++ b/docs/kratos/social-signin/30_apple.mdx @@ -182,8 +182,8 @@ Follow these steps to add Apple as a social sign-in provider to your project usi 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. +This flow uses the native Apple SDK and does not require a browser. This results in a signed `id_token` on the client side +(typically your app) which is exchanged at Ory for a session token. The following steps are required to integrate the Apple SDK with Ory: @@ -199,7 +199,7 @@ The `id_token` is verified using Apple's publicly available signing keys, availa 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 +:::info 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` @@ -209,9 +209,9 @@ 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" +import signInWithAppleSnippet from "!!raw-loader!@site/code-examples/sdk/typescript/src/selfservice/registration/apple-social-sign-in-native.ts" -{revokeOtherSessionsReact} +{signInWithAppleSnippet} ``` ## Troubleshooting diff --git a/docs/kratos/social-signin/96_native-apps.mdx b/docs/kratos/social-signin/96_native-apps.mdx index ecefeb425..1f2ab06a1 100644 --- a/docs/kratos/social-signin/96_native-apps.mdx +++ b/docs/kratos/social-signin/96_native-apps.mdx @@ -23,8 +23,9 @@ this: :::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. +Apple and Google support 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) and +[Google social sign-in](./10_google.mdx#using-the-google-sdk-on-native-apps) for more information. :::