Skip to content

Commit 4843802

Browse files
Neelansh Sahaicy245
authored andcommitted
Move Shrine app to main
1 parent c407cd3 commit 4843802

File tree

200 files changed

+15887
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

200 files changed

+15887
-4
lines changed

CredentialProvider/MyVault/app/build.gradle.kts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ plugins {
2121

2222
android {
2323
namespace = "com.example.android.authentication.myvault"
24-
2524
compileSdk = 35
26-
2725
defaultConfig {
2826
applicationId = "com.example.android.authentication.myvault"
2927
minSdk = 34

Shrine/README.md

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
# Credential Manager Sample App
2+
3+
This is the repository for the Credential Manager API code integration app,
4+
also known as the **"Shrine"** app.
5+
6+
The Shrine app is a fully functional Android app built with Kotlin and Jetpack Compose.
7+
This sample app is built to share a working sample of Credential Manager APIs in Android
8+
and help visualize the workflow. This sample code is designed to help you understand the
9+
workflow better and allow you to estimate the level of effort needed to incorporate
10+
Credential Manager with your own apps.
11+
12+
## Features
13+
14+
This sample app implements the following use cases:
15+
16+
* Create an account using username and set the session using password.
17+
* Generate a new passkey for an existing account
18+
* Store the credentials for created accounts in the user's Google Password Manager account.
19+
* Sign in flow with passkeys support
20+
* Sign in flow with restore credentials support
21+
* Logout from the account.
22+
23+
## Requirements
24+
25+
* Latest release of [Android Studio](https://developer.android.com/studio)
26+
* Java 11 or higher
27+
* A web browser with the ability to access [Glitch](https://glitch.com/).
28+
29+
## Typical account creation and login flow
30+
31+
* Launch the app
32+
* Create an account by sending any username to the server
33+
* Set a session by sending a password in step 2
34+
* Register user credentials using your fingerprint sensor
35+
* From the list of passkeys options shown in the bottom sheet, select the correct passkey option to login
36+
* Logout of the application and close the app
37+
* [Optional] Create multiple accounts and switch accounts to test the implementation
38+
39+
40+
## How to setup your own Glitch.me server
41+
42+
The Shrine app sends requests to a Glitch.me server, and out of the box this code example has been
43+
configured to use a Glitch instance that we've created. To use your own Glitch-hosted backend,
44+
follow these steps. The backend code uses your Android package and SHA fingerprint, and you will
45+
update these on the server.
46+
47+
1. Go to the edit page of the website at [https://glitch.com/edit/#!/credential-manager-app-test](https://glitch.com/edit/#!/credential-manager-app-test)
48+
49+
2. Find the ***"Remix to Edit"*** button at the top right corner. By pressing the button, you can fork the code and continue this tutorial with your own version of the project and services.
50+
51+
3. To use the API on an Android app, you need to associate it with a website and share credentials between them. To set this up, you'll use [Digital Asset Links](https://developer.android.com/training/sign-in/passkeys#add-support-dal). Digital Asset Links files are used to declare associations by hosting a JSON file on your website, and adding a link to this file to your app's manifest. Normally, you'll define an association between your app and the website by creating a JSON file and put it at `.well-known/assetlinks.json` on your HTTPS server. **For this demo, we have a server code that creates an `assetlinks.json` file automatically, just by adding the following environment params to the `.env` file in Glitch:**
52+
53+
1. In the Glitch left nav Files section, click on the `.env` file. This opens up your project's Environment Config. Fill in the following values:
54+
55+
2. `HOSTNAME`: The name of your newly created Glitch service. The project name is found on top left of your Glitch project screen. It'll be something like `peaceful-banana-fern`. Paste or type in the name of your Glitch project into the `HOSTNAME` section.
56+
57+
3. `ANDROID_PACKAGENAME`: The package name of your app, such as `com.google.credentialmanager.sample`. You can find the package name in your project's app-level `build.gradle` file as the value of the `applicationId` property within the `android` block.
58+
59+
4. `ANDROID_SHA256HASH`: SHA-256 hash of your signing certificate. To get the SHA-256 hash of your developer signing certificate, use the following command: `keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore`. The default password of the debug keystore is "android". The SHA256 value appears under Certificate fingerprints. (`75:89:78:74:...`)
60+
61+
62+
4. In your `build.gradle`'s `android` block, find the fields for `buildConfigField` and `resValue`, and update the following values.
63+
64+
1. `buildConfigField / API_BASE_URL`: The URL of your new Glitch server's API. It'll be the full URL + /path appended to the end. For example: `https://peaceful-banana-fern.glitch.me/auth`
65+
66+
2. `resValue / host`: The root URL for your server. For example: [https://peaceful-banana-fern.glitch.me](https://peaceful-banana-fern.glitch.me)
67+
68+
69+
5. Sync your `build.gradle` changes by running **File > Sync Project with Gradle Files**.
70+
71+
6. Test building your app. Run a physical or emulated device that has a valid and passkey-enabled Google account set up, then run your app on it. You should see the Shrine app home screen appear, with Sign In and Sign Up buttons. Don't click anything just yet, you'll do that in the next step.
72+
73+
74+
## Integration
75+
76+
Follow these steps to test Credential Manager integration. In the app, look for a toast to appear to indicate a response success or failure on each step.
77+
78+
### Create an account for username on the server
79+
80+
1. When your app runs the first time, you should see a screen with buttons for Sign In and Sign Up. Click the **Sign Up** button. The **Create Account** screen appears.
81+
82+
2. Enter an email address and unique password and click the **Submit** button.
83+
84+
3. You should now see a **Create a passkey** screen. Click **Create a passkey**.
85+
86+
4. You should see a Google Password Manager bottom sheet appear, offering to save your credentials. Click **Continue**.
87+
88+
5. The Shrine app should then show the **Create a passkey** screen. Click the **Create a passkey** button and a Google Password Manager bottom sheet should appear that offers to create a passkey for your app. Click **Continue**. You should now see the Shrine main menu.
89+
90+
6. Click **Step 1: Send Username** after adding a username and email in the 1st field. For demo purposes, the app and the server will accept any username.
91+
92+
7. Check the username, and create a new account if it doesn't exist.
93+
94+
8. Set a `username` in the session.
95+
96+
9. Wait for the toast to appear saying "Username verified successfully". If you don't see toast, check the logs for errors.
97+
98+
99+
### **Set a session on server**
100+
101+
This step demonstrates if developers want to do additional authentication (2FA). This step shows how 2FA can be done while using passkeys for authentication.
102+
103+
1. Check **Step 2: Send Password**. Above that field, add any password. Type and send the request.
104+
105+
2. Verify the user credential and let the user sign-in. No preceding registration is required.
106+
107+
3. Wait for the toast to appear that says "Session-id stored successfully, Do register!"
108+
109+
4. If you don't see toast, check the logs for errors.
110+
111+
112+
### **Pass required information to a passkey creation prompt**
113+
114+
This section describes how to send a registration request to the server and pass the required information to a passkey creation prompt.
115+
116+
1. Register the passkey credential. Inside `AuthRepository.kt`, find `registerRequest`.
117+
118+
2. Once the request is sent from the client, this method calls the server API `/auth/registerRequest`. The API returns an `ApiResult` with all the `PublicKeyCredentialCreationOptions` that the client needs to generate a new credential.
119+
120+
121+
### **Create a passkey**
122+
123+
In this section, you'll create a passkey with the response received from `/registerRequest`.
124+
125+
1. Parse the params as per needed for the create credentials call. Call `createPasskey()` from `Auth.kt`
126+
127+
2. Give users the choice to enroll a passkey and use it for re-authentication by registering a user credential using a `CreatePublicKeyCredentialRequest()` object.
128+
129+
3. This method calls `createCredential()` from *Credential Manager API*, which registers a user credential that can be used to authenticate the user to the app in the future. This method launches framework UI flows for a user to view their registration options, grant consent, etc.
130+
131+
4. Use your fingerprint or other auth. Methods from your device to register.
132+
133+
134+
### **Send the registration response and register a user credential**
135+
136+
This section describes how to send a registration response back to the server and register a user credential on a server.
137+
138+
- Call `/registerResponse`. This `registerResponse` method is called after the user interface successfully generates a new credential, and you want to send it back to the server.
139+
140+
- Use the response received from the `createPasskey()` call and pass it back to your server.
141+
142+
- Remember the ID of your local key so you can distinguish it from other keys registered on the server. In the `PublicKeyCredential` object, use the `rawId` property.
143+
144+
- The returned value contains a list of all the credentials registered on the server, including the new one.
145+
146+
147+
### **How to retrieve previously stored credentials for user’s account**
148+
149+
You now have a credential registered on the app and the server. You can now use it to let the user sign in.
150+
151+
1. Initiate a server check:
152+
153+
- Open the file `AuthRepository.kt`.
154+
155+
- Examine the `signinRequest` object.
156+
157+
- Send a request to your server to confirm if Credential Manager APIs can be used for user sign-in.
158+
159+
- Provide the `sessionId` and `credentialId` (which were stored locally) as data for this request.
160+
161+
162+
2. Prompt the user for stored credentials:
163+
164+
- If the server request is successful, call the `getPasskey()` function from the `Auth.kt` file to display the user's stored credentials.
165+
166+
3. Configure the retrieval request:
167+
168+
- Create a `GetCredentialRequest()`.
169+
170+
- Provide the previously created registration options to this request.
171+
172+
- For the `isAutoSelectAllowed()` flag:
173+
174+
175+
- Set to `true` if you want a single stored credential to be automatically selected.
176+
177+
- Set to `false` to require manual selection.
178+
179+
180+
4. Retrieve credentials:
181+
182+
- Use `PublicKeyCredentialOptions` with the `GetCredentialRequest` to retrieve all the user's eligible credentials.
183+
184+
- Ensure that the `requestJson` argument is in a valid WebAuthn JSON format.
185+
186+
187+
5. Display the credential selection interface:
188+
189+
190+
- Call `CredentialManager.getCredential()` to display a bottom sheet interface.
191+
192+
- This UI displays a list of previously saved credentials. The user can then select a credential and provide consent to proceed with authentication.
193+
194+
195+
### **Send a sign-in response and authenticate the user**
196+
197+
This section describes how to send a sign-in response to the server and authenticate your user.
198+
199+
1. Call `signinResponse` from `AuthRespository.kt`. Pass the response and credential to the method as parameters.
200+
201+
2. If successful, the user has been signed in and you can redirect them to the home screen.
202+
203+
204+
### **Restore credentials of a returning user on a new device**
205+
206+
This section describes how to implement restore credentials
207+
208+
1. On a successful user authentication, create a Restore Key
209+
210+
1. Call `AuthRepository`'s `registerPasskeyCreationRequest` method
211+
212+
2. With the PasskeyCreationRequest recieved from the above method, call `CredentialManagerUtils`'s `createRestoreKey` method
213+
214+
3. Then call `AuthRepository`'s `registerPasskeyCreationResponse` method
215+
216+
217+
2. Once on a new device, check if there is any restore key present on the device or not (brought to the new device in the process of Backup and Restore)
218+
219+
1. Call `AuthRepository`'s `signInWithPasskeyOrPasswordRequest` method
220+
221+
2. With the PasskeyCreationRequest recieved from the above method, call `CredentialManagerUtils`'s `getRestoreKey` method
222+
223+
3. If there is a RestoreKey present this will return a `GenericCredentialManagerResponse.GetCredentialSuccess` else this will return a `GenericCredentialManagerResponse.Error`
224+
225+
226+
3. Sign in using the found Restore Key
227+
228+
1. If a restore key is found in the above step, simply use it to sign-in using `AuthRepository`'s `signInWithPasskeysResponse` method
229+
230+
231+
4. Delete a Restore Key
232+
233+
1. If a user logs out of the app, make sure to clear the stored restore key by calling `CredentialManagerUtils`'s `deleteRestoreKey`
234+
235+
236+
## **Specific use case handling**
237+
238+
- When there are no passkeys associated with accounts registered, the developer should catch the exception code and let the user know that first he needs to create a passkey before they try to fetch it.
239+
240+
- For Begin Sign In Failure: 16: Caller has been temporarily blocked due to too many canceled sign-in prompt errors: This is a FIDO-specific error.
241+
242+
- For Begin Sign In Failure: 8: Unknown internal error. If the phone isn't set up properly with a Google account, the passkey JSON is being created incorrectly.
243+
244+
- For `publickeycredential.CreatePublicKeyCredentialDomException`: The incoming request cannot be validated: This means your application package ID is not registered with your server. Validate this with your server code.
245+
246+
247+
### **How to build a debug signed version**
248+
249+
To build a debug signed version of this sample app, you need to update the `API_BASE_URL` to `https://credential-manager-app-test.glitch.me/auth` and `host` field to `https://credman-glitch-sample.glitch.me` under `buildConfigField` in your `build.gradle` file.
250+
251+
## **License**
252+
253+
Shrine is distributed under the terms of the Apache License (Version 2.0). See the license for more information.
254+
255+
**

Shrine/app/.gitignore

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# built application files
2+
*.apk
3+
*.ap_
4+
5+
# Mac files
6+
.DS_Store
7+
8+
# files for the dex VM
9+
*.dex
10+
11+
# Java class files
12+
*.class
13+
14+
# generated files
15+
bin/
16+
gen/
17+
18+
# Ignore gradle files
19+
.gradle/
20+
build/
21+
22+
# Local configuration file (sdk path, etc)
23+
local.properties
24+
25+
# Proguard folder generated by Eclipse
26+
proguard/
27+
proguard-project.txt
28+
29+
# Eclipse files
30+
.project
31+
.classpath
32+
.settings/
33+
34+
# Android Studio/IDEA
35+
*.iml
36+
.idea

0 commit comments

Comments
 (0)