Tutorial: Signin

Course Schedule

This tutorial may be completed individually or in teams of at most 2. You can partner differently for each tutorial.

In this tutorial, we add Google Sign-In, with biometric authentication, to Chatter. We will build on the code base from the second tutorial, Chatter.

The course back-end server mada.eecs.umich.edu is not available for this tutorial.

Expected behavior

Posting a new chatt with authentication:

DISCLAIMER: the video demo shows you one aspect of the app’s behavior. It is not a substitute for the spec. If there are any discrepancies between the demo and the spec, please follow the spec. The spec is the single source of truth. If the spec is ambiguous, please consult the teaching staff for clarification.

Objectives

Learn:

Using Google Sign-In for authentication

The goals of this tutorial are twofold: first, to introduce you to use of OAuth 2.0 and OpenID Connect for authentication as implemented by Google Sign-In, an iOS SDK that is part of the Google Identity Platform. Second, to introduce you to Apple’s Keychain with biometric authentication. Apple, Meta, X, WeChat, among others, all use OAuth 2.0. We’ve chosen Google Sign-in for illustrative purposes as it seems to be the most popular and accessible.

DISCLAIMER: this tutorial is not an exercise in designing a secure authentication protocol. It is only meant to familiarize you with some of the authentication tools available in the mobile environment. The protocol implemented here has not been vetted by a security expert.

In this tutorial, we assume that authentication is authorization. As long as you’re authenticated, you can perform any of the app’s functions. We don’t separately check whether you’re authorized to perform each task.

Here’s the authentication flow:

  1. We’ve designed the app to require authentication only for posting chatts, not for viewing them. To reduce number of trips the app makes to secure storage, we retrieve any previously stored authorization token (called chatterID) at the launch of the app—it is not an error to not have a previously stored chatterID.

  2. When the user tries to post a chatt, if we don’t have a valid chatterID, we first obtain one. Otherwise, we post the chatt as usual (as in the Chatter tutorial).

  3. We need a valid Google ID Token to obtain a chatterID. We first check if the user is already signed in or if their ID Token is still valid and can be refreshed. Otherwise, we let the user sign in and obtain a new ID Token.

  4. Once the user has a valid ID Token, we contact the chatterd back end with the ID Token and the app’s Google Client ID to obtain a chatterID.

  5. Upon receiving a new chatterID, we save it to the device’s secured storage.

  6. While the chatterID is valid, i.e., its lifetime hasn’t expired, we can use it to post chatts without further checking the user’s sign-in status.

Later we will add biometric check to control access to the device’s secure storage:

  1. to retrieve previously stored chatterID at launch (#1 above)
  2. to save or update chatterID in secured storage (#5)

Our use of biometric check does not make the sign-in process itself any more secure. If you don’t have chatterID stored from a previous run of the app, or if storing your chatterID failed for whatever reasons, you can still sign in with Google and post chatt normally. Even without a stored chatterID, as long as your previous Google Sign-in has not expired, you can also still post chatt without being prompted to sign in again, as per standard Google Sign-in behavior. The only purpose of the biometric check is to control access to the stored chatterID across invocations of the app.

Signing out is not logging out

WARNING: With Google Sign-In, signing out only signs the user out of the app, it does not log the user out of Google on the device. Subsequently, all the user has to do to sign back in on the app is to select their account. Google will not challenge them for password again. Apparently, this is OAuth 2.0 standard-compliant behavior, including, for example for X sign-in. The user is thus left vulnerable on public computers (see github and stackoverflow postings). Further, if the app is killed or force closed from outside the app, the user will not be signed out. The only way to sign a user out from the device is through the user’s Manage your Google Account button on a browser. Navigate to Security > Your devices. Click on the three vertical dots on the upper right of your device’s card on the web page and choose Sign out.

Modified Chatter API

To retrieve chatts, we use the same getchatts API endpoint from the chatter tutorial, unmodified.

To post a chatt, users must now be authenticated first. We add two APIs to Chatter:

Using this syntax:

url-endpoint
-> request: data sent to Server
<- response: data sent to Client

the additional protocol handshakes consist of:

/adduser
-> HTTP POST { clientID, idToken }
<- { chatterID, lifetime } 200 OK

If the idToken fails authentication, adduser returns HTTP status code 401, “Unauthorized”.

/postauth
-> HTTP POST { chatterID, message }
<- {} 200 OK

If the lifetime of chatterID has expired, postauth returns HTTP status code 401, “Unauthorized”.

New Chatter API data formats

The data format adduser expects is, assuming use of Google Signin for authentication:

{
    "clientID": "YOUR_APP'S_OAUTH2.0_CLIENT_ID",
    "idToken": "YOUR_GOOGLE_ID_TOKEN"
}

where:

The data format postauth expects is:

{
    "chatterID": "YOUR_CHATTER_ID",
    "message": "Chitt chatts"
}

where YOUR_CHATTER_ID is the chatterID returned by the adduser API above.

Assignment specs

The suggested work flow is to work on the front end until you can obtain the ID Token issued by Google Sign-in, then switch to work on the back end, and then return to finish up the front end:

Upgrade one of the alternative back-end servers: unlike the other tutorials, the back end of this one is rather more substantive:

If you choose to work on the back end first, be prepared that you won’t be able to test it until you have obtained a Google ID Token part way through the implementation of your front end.


Prepared by Sugih Jamin Last updated: March 11th, 2026