Skip to content

Commit 94c2b8f

Browse files
authored
Add siwg snippets (#491)
1 parent e5789e4 commit 94c2b8f

File tree

3 files changed

+189
-0
lines changed

3 files changed

+189
-0
lines changed

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ androidx-window-java = "1.3.0"
2727
androidxHiltNavigationCompose = "1.2.0"
2828
appcompat = "1.7.0"
2929
coil = "2.7.0"
30+
android-googleid = "1.1.1"
3031
# @keep
3132
compileSdk = "35"
3233
compose-latest = "1.7.8"
@@ -135,6 +136,7 @@ androidx-window = { module = "androidx.window:window", version.ref = "androidx-w
135136
androidx-window-core = { module = "androidx.window:window-core", version.ref = "androidx-window-core" }
136137
androidx-window-java = {module = "androidx.window:window-java", version.ref = "androidx-window-java" }
137138
androidx-work-runtime-ktx = "androidx.work:work-runtime-ktx:2.10.0"
139+
android-identity-googleid = {module = "com.google.android.libraries.identity.googleid:googleid", version.ref = "android-googleid"}
138140
appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
139141
coil-kt-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
140142
compose-foundation = { module = "androidx.wear.compose:compose-foundation", version.ref = "wearComposeFoundation" }

identity/credentialmanager/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ dependencies {
5555
// Android 13 and below.
5656
implementation(libs.androidx.credentials.play.services.auth)
5757
// [END android_identity_gradle_dependencies]
58+
// [START android_identity_siwg_gradle_dependencies]
59+
implementation(libs.androidx.credentials)
60+
implementation(libs.androidx.credentials.play.services.auth)
61+
implementation(libs.android.identity.googleid)
62+
// [END android_identity_siwg_gradle_dependencies]
5863
debugImplementation(libs.androidx.compose.ui.tooling)
5964
debugImplementation(libs.androidx.compose.ui.test.manifest)
6065
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.identity.credentialmanager
18+
19+
import android.content.Context
20+
import android.util.Log
21+
import androidx.credentials.CredentialManager
22+
import androidx.credentials.CustomCredential
23+
import androidx.credentials.GetCredentialRequest
24+
import androidx.credentials.GetCredentialResponse
25+
import androidx.credentials.PasswordCredential
26+
import androidx.credentials.PublicKeyCredential
27+
import androidx.credentials.exceptions.GetCredentialException
28+
import com.google.android.libraries.identity.googleid.GetGoogleIdOption
29+
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption
30+
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
31+
import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException
32+
import kotlinx.coroutines.coroutineScope
33+
import kotlin.math.sign
34+
35+
const val WEB_CLIENT_ID = ""
36+
class SignInWithGoogleFunctions (
37+
context: Context,
38+
) {
39+
private val credentialManager = CredentialManager.create(context)
40+
private val activityContext = context
41+
// Placeholder for TAG log value.
42+
val TAG = ""
43+
44+
fun createGoogleIdOption(nonce: String): GetGoogleIdOption {
45+
// [START android_identity_siwg_instantiate_request]
46+
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
47+
.setFilterByAuthorizedAccounts(true)
48+
.setServerClientId(WEB_CLIENT_ID)
49+
.setAutoSelectEnabled(true)
50+
// nonce string to use when generating a Google ID token
51+
.setNonce(nonce)
52+
.build()
53+
// [END android_identity_siwg_instantiate_request]
54+
55+
return googleIdOption
56+
}
57+
58+
private val googleIdOption = createGoogleIdOption("")
59+
60+
suspend fun signInUser() {
61+
// [START android_identity_siwg_signin_flow_create_request]
62+
val request: GetCredentialRequest = GetCredentialRequest.Builder()
63+
.addCredentialOption(googleIdOption)
64+
.build()
65+
66+
coroutineScope {
67+
try {
68+
val result = credentialManager.getCredential(
69+
request = request,
70+
context = activityContext,
71+
)
72+
handleSignIn(result)
73+
} catch (e: GetCredentialException) {
74+
// Handle failure
75+
}
76+
}
77+
// [END android_identity_siwg_signin_flow_create_request]
78+
}
79+
80+
// [START android_identity_siwg_signin_flow_handle_signin]
81+
fun handleSignIn(result: GetCredentialResponse) {
82+
// Handle the successfully returned credential.
83+
val credential = result.credential
84+
val responseJson: String
85+
86+
when (credential) {
87+
88+
// Passkey credential
89+
is PublicKeyCredential -> {
90+
// Share responseJson such as a GetCredentialResponse to your server to validate and
91+
// authenticate
92+
responseJson = credential.authenticationResponseJson
93+
}
94+
95+
// Password credential
96+
is PasswordCredential -> {
97+
// Send ID and password to your server to validate and authenticate.
98+
val username = credential.id
99+
val password = credential.password
100+
}
101+
102+
// GoogleIdToken credential
103+
is CustomCredential -> {
104+
if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
105+
try {
106+
// Use googleIdTokenCredential and extract the ID to validate and
107+
// authenticate on your server.
108+
val googleIdTokenCredential = GoogleIdTokenCredential
109+
.createFrom(credential.data)
110+
// You can use the members of googleIdTokenCredential directly for UX
111+
// purposes, but don't use them to store or control access to user
112+
// data. For that you first need to validate the token:
113+
// pass googleIdTokenCredential.getIdToken() to the backend server.
114+
// see [validation instructions](https://developers.google.com/identity/gsi/web/guides/verify-google-id-token)
115+
} catch (e: GoogleIdTokenParsingException) {
116+
Log.e(TAG, "Received an invalid google id token response", e)
117+
}
118+
} else {
119+
// Catch any unrecognized custom credential type here.
120+
Log.e(TAG, "Unexpected type of credential")
121+
}
122+
}
123+
124+
else -> {
125+
// Catch any unrecognized credential type here.
126+
Log.e(TAG, "Unexpected type of credential")
127+
}
128+
}
129+
}
130+
// [END android_identity_siwg_signin_flow_handle_signin]
131+
132+
fun createGoogleSignInWithGoogleOption(nonce: String): GetSignInWithGoogleOption {
133+
// [START android_identity_siwg_get_siwg_option]
134+
val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder(
135+
serverClientId = WEB_CLIENT_ID
136+
).setNonce(nonce)
137+
.build()
138+
// [END android_identity_siwg_get_siwg_option]
139+
140+
return signInWithGoogleOption
141+
}
142+
143+
// [START android_identity_handle_siwg_option]
144+
fun handleSignInWithGoogleOption(result: GetCredentialResponse) {
145+
// Handle the successfully returned credential.
146+
val credential = result.credential
147+
148+
when (credential) {
149+
is CustomCredential -> {
150+
if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
151+
try {
152+
// Use googleIdTokenCredential and extract id to validate and
153+
// authenticate on your server.
154+
val googleIdTokenCredential = GoogleIdTokenCredential
155+
.createFrom(credential.data)
156+
} catch (e: GoogleIdTokenParsingException) {
157+
Log.e(TAG, "Received an invalid google id token response", e)
158+
}
159+
}
160+
else {
161+
// Catch any unrecognized credential type here.
162+
Log.e(TAG, "Unexpected type of credential")
163+
}
164+
}
165+
166+
else -> {
167+
// Catch any unrecognized credential type here.
168+
Log.e(TAG, "Unexpected type of credential")
169+
}
170+
}
171+
}
172+
// [END android_identity_handle_siwg_option]
173+
174+
fun googleIdOptionFalseFilter() {
175+
// [START android_identity_siwg_instantiate_request_2]
176+
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
177+
.setFilterByAuthorizedAccounts(false)
178+
.setServerClientId(WEB_CLIENT_ID)
179+
.build()
180+
// [END android_identity_siwg_instantiate_request_2]
181+
}
182+
}

0 commit comments

Comments
 (0)