Ini adalah panduan ketiga di add-on Classroom seri panduan kami.
Dalam panduan ini, Anda menangani kunjungan berulang ke add-on kami secara otomatis mengambil kredensial yang sebelumnya diberikan oleh pengguna. Kemudian, Anda mengarahkan pengguna ke halaman tempat mereka dapat segera mengeluarkan permintaan API. Tindakan ini diperlukan untuk add-on Classroom.
Dalam panduan ini, Anda akan menyelesaikan hal-hal berikut:
- Implementasikan penyimpanan persisten untuk kredensial pengguna.
- Ambil dan evaluasi parameter kueri add-on
login_hint
. Ini adalah nomor ID Google unik dari pengguna yang login.
Setelah selesai, Anda dapat sepenuhnya memberikan otorisasi kepada pengguna di aplikasi web Anda dan melakukan panggilan ke Google API.
Memahami parameter kueri iframe
Classroom akan memuat URI Penyiapan Lampiran add-on setelah
saat membuka. Ruang kelas
menambahkan beberapa parameter kueri GET
ke URI; ini berisi data bermanfaat
informasi kontekstual. Misalnya, jika URI Penemuan Lampiran Anda adalah
https://example.com/addon
, Classroom akan membuat iframe dengan
URL sumber yang disetel ke
https://example.com/addon?courseId=XXX&itemId=YYY&itemType=courseWork&addOnToken=ZZZ
,
dengan XXX
, YYY
, dan ZZZ
adalah ID string. Lihat panduan iframe untuk
penjelasan terperinci
dari skenario ini.
Ada lima kemungkinan parameter kueri untuk URL penemuan:
courseId
: ID kursus Classroom saat ini.itemId
: ID item aliran yang sedang diedit atau dibuat oleh pengguna.itemType
: Jenis item aliran yang dibuat atau diedit pengguna, salah satucourseWork
,courseWorkMaterial
, atauannouncement
.addOnToken
: Token yang digunakan untuk memberi otorisasi Tindakan add-on Classroom.login_hint
: ID Google pengguna saat ini.
Panduan ini membahas login_hint
. Pengguna diarahkan berdasarkan apakah
parameter kueri disediakan, baik untuk alur otorisasi
jika tidak ada, atau untuk
halaman penemuan add-on jika ada.
Mengakses parameter kueri
Parameter kueri diteruskan ke aplikasi web Anda dalam string URI. Menyimpan nilai-nilai ini dalam sesi Anda; mereka digunakan dalam alur otorisasi dan menyimpan dan mengambil informasi tentang pengguna. Parameter kueri ini hanya yang diteruskan saat add-on pertama kali dibuka.
Python
Buka definisi rute Flask (routes.py
jika Anda
dengan mengikuti contoh yang kami berikan). Di bagian atas rute landing add-on
(/classroom-addon
dalam contoh yang kami berikan), ambil dan simpan
Parameter kueri login_hint
:
# If the login_hint query parameter is available, we'll store it in the session.
if flask.request.args.get("login_hint"):
flask.session["login_hint"] = flask.request.args.get("login_hint")
Pastikan login_hint
(jika ada) disimpan dalam sesi. Ini adalah
tempat yang tepat untuk
menyimpan nilai-nilai ini; bersifat sementara
dan Anda akan menerima
nilai baru saat add-on dibuka.
# It's possible that we might return to this route later, in which case the
# parameters will not be passed in. Instead, use the values cached in the
# session.
login_hint = flask.session.get("login_hint")
# If there's still no login_hint query parameter, this must be their first
# time signing in, so send the user to the sign in page.
if login_hint is None:
return start_auth_flow()
Java
Membuka rute landing add-on di class pengontrol
(/addon-discovery
dalam AuthController.java
dalam contoh yang diberikan). Di
awal rute ini, ambil dan simpan kueri login_hint
.
/** Retrieve the login_hint query parameter from the request URL if present. */
String login_hint = request.getParameter("login_hint");
Pastikan login_hint
(jika ada) disimpan dalam sesi. Ini adalah
tempat yang tepat untuk
menyimpan nilai-nilai ini; bersifat sementara
dan Anda akan menerima
nilai baru saat add-on dibuka.
/** If login_hint wasn't sent, use the values in the session. */
if (login_hint == null) {
login_hint = (String) session.getAttribute("login_hint");
}
/** If the there is still no login_hint, route the user to the authorization
* page. */
if (login_hint == null) {
return startAuthFlow(model);
}
/** If the login_hint query parameter is provided, add it to the session. */
else if (login_hint != null) {
session.setAttribute("login_hint", login_hint);
}
Menambahkan parameter kueri ke alur otorisasi
Parameter login_hint
harus diteruskan ke server autentikasi Google
juga. Hal ini memudahkan proses otentikasi; jika aplikasi Anda mengetahui
pengguna yang mencoba mengotentikasi, server menggunakan
petunjuk itu untuk menyederhanakan
alur login dengan mengisi otomatis kolom email di formulir login.
Python
Buka rute otorisasi di file server Flask Anda (/authorize
dalam contoh yang kami berikan). Tambahkan argumen login_hint
ke panggilan ke
flow.authorization_url
.
authorization_url, state = flow.authorization_url(
# Enable offline access so that you can refresh an access token without
# re-prompting the user for permission. Recommended for web server apps.
access_type="offline",
# Enable incremental authorization. Recommended as a best practice.
include_granted_scopes="true",
# The user will automatically be selected if we have the login_hint.
login_hint=flask.session.get("login_hint"),
Java
Buka metode authorize()
di class AuthService.java
. Tambah
login_hint
sebagai parameter ke metode, dan tambahkan login_hint
dan argumen ke pembuat URL otorisasi.
String authUrl = flow
.newAuthorizationUrl()
.setState(state)
.set("login_hint", login_hint)
.setRedirectUri(REDIRECT_URI)
.build();
Menambahkan penyimpanan persisten untuk kredensial pengguna
Jika Anda menerima login_hint
sebagai parameter kueri saat add-on dimuat, ini adalah
indikasi bahwa pengguna telah menyelesaikan
alur otorisasi untuk
aplikasi. Anda harus mengambil kredensial sebelumnya, bukan memaksa
mereka untuk masuk lagi.
Ingatlah bahwa Anda menerima token refresh setelah menyelesaikan alur otorisasi. Simpan token ini; digunakan kembali untuk mendapatkan token akses, yang berumur pendek dan diperlukan untuk menggunakan Google API. Anda simpan sebelumnya kredensial ini dalam sesi, tetapi Anda perlu menyimpan kredensial tersebut untuk menangani kunjungan berulang.
Menentukan skema Pengguna dan menyiapkan database
Menyiapkan skema database untuk User
.
Python
Menentukan Skema Pengguna
User
berisi atribut berikut:
id
: ID Google pengguna. Ini harus cocok dengan nilai yang diberikan dalam Parameter kuerilogin_hint
.display_name
: Nama depan dan nama belakang pengguna, misalnya "Alex Smith".email
: Alamat email pengguna.portrait_url
: URL foto profil pengguna.refresh_token
: Token refresh yang diperoleh sebelumnya.
Contoh ini mengimplementasikan penyimpanan menggunakan SQLite, yang secara native didukung oleh
Python. Class ini menggunakan modul flask_sqlalchemy
untuk memfasilitasi database kita
otomatisasi pengelolaan biaya.
Menyiapkan database
Pertama, tentukan lokasi file untuk database kita. Buka server Anda
file konfigurasi (config.py
dalam contoh yang kami berikan) dan tambahkan
mengikuti.
import os
# Point to a database file in the project root.
DATABASE_FILE_NAME = os.path.join(
os.path.abspath(os.path.dirname(__file__)), 'data.sqlite')
class Config(object):
SQLALCHEMY_DATABASE_URI = f"sqlite:///{DATABASE_FILE_NAME}"
SQLALCHEMY_TRACK_MODIFICATIONS = False
Ini akan mengarahkan Flask ke file data.sqlite
di direktori yang sama dengan
File main.py
.
Selanjutnya, buka direktori modul Anda dan buat file models.py
baru.
Nilai ini adalah webapp/models.py
jika Anda mengikuti contoh yang kami berikan. Tambah
baris berikut ke file baru untuk menentukan tabel User
, dengan mengganti
nama modul untuk webapp
jika berbeda.
from webapp import db
# Database model to represent a user.
class User(db.Model):
# The user's identifying information:
id = db.Column(db.String(120), primary_key=True)
display_name = db.Column(db.String(80))
email = db.Column(db.String(120), unique=True)
portrait_url = db.Column(db.Text())
# The user's refresh token, which will be used to obtain an access token.
# Note that refresh tokens will become invalid if:
# - The refresh token has not been used for six months.
# - The user revokes your app's access permissions.
# - The user changes passwords.
# - The user belongs to a Google Cloud organization
# that has session control policies in effect.
refresh_token = db.Column(db.Text())
Terakhir, di file __init__.py
modul Anda, tambahkan kode berikut untuk diimpor
model baru dan membuat database.
from webapp import models
from os import path
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
# Initialize the database file if not created.
if not path.exists(config.DATABASE_FILE_NAME):
db.create_all()
Java
Menentukan Skema Pengguna
User
berisi atribut berikut:
id
: ID Google pengguna. Ini harus cocok dengan nilai yang diberikan dalam Parameter kuerilogin_hint
.email
: Alamat email pengguna.
Buat file schema.sql
di direktori resources
modul. Musim semi
membaca file ini dan membuat skema untuk database yang sesuai.
Tentukan tabel dengan nama tabel, users
, dan kolom untuk diwakili
atribut User
, id
dan email
.
CREATE TABLE IF NOT EXISTS users (
id VARCHAR(255) PRIMARY KEY, -- user's unique Google ID
email VARCHAR(255), -- user's email address
);
Buat class Java untuk menentukan model User
untuk database. Ini adalah
User.java
dalam contoh yang diberikan.
Tambahkan anotasi @Entity
untuk menunjukkan bahwa ini adalah POJO yang dapat
disimpan ke {i>database<i}. Tambahkan anotasi @Table
dengan
nama tabel yang sesuai yang dikonfigurasi di schema.sql
.
Perhatikan bahwa contoh kode menyertakan konstruktor dan penyetel untuk keduanya
. Konstruktor dan penyetel digunakan di
AuthController.java
untuk membuat atau memperbarui pengguna di database. Anda
mungkin juga menyertakan pengambil dan metode toString
sesuai kebutuhan, tetapi untuk
panduan khusus ini, metode-metode tersebut tidak digunakan dan dihilangkan dari
contoh kode di halaman ini agar lebih singkat.
/** An entity class that provides a model to store user information. */
@Entity
@Table(name = "users")
public class User {
/** The user's unique Google ID. The @Id annotation specifies that this
* is the primary key. */
@Id
@Column
private String id;
/** The user's email address. */
@Column
private String email;
/** Required User class no args constructor. */
public User() {
}
/** The User class constructor that creates a User object with the
* specified parameters.
* @param id the user's unique Google ID
* @param email the user's email address
*/
public User(String id, String email) {
this.id = id;
this.email = email;
}
public void setId(String id) { this.id = id; }
public void setEmail(String email) { this.email = email; }
}
Membuat antarmuka bernama UserRepository.java
untuk menangani operasi CRUD
ke {i>database<i}. Antarmuka ini memperluas antarmuka CrudRepository
.
/** Provides CRUD operations for the User class by extending the
* CrudRepository interface. */
@Repository
public interface UserRepository extends CrudRepository<User, String> {
}
Class pengontrol memfasilitasi komunikasi antara klien dan
repositori resource. Oleh karena itu, update konstruktor class pengontrol untuk memasukkan
class UserRepository
.
/** Declare UserRepository to be used in the Controller class constructor. */
private final UserRepository userRepository;
/**
* ...
* @param userRepository the class that interacts with User objects stored in
* persistent storage.
*/
public AuthController(AuthService authService, UserRepository userRepository) {
this.authService = authService;
this.userRepository = userRepository;
}
Menyiapkan database
Untuk menyimpan informasi terkait Pengguna, gunakan database H2 yang secara intrinsik
didukung dalam Spring Boot. {i>Database<i} ini juga digunakan pada
panduan untuk menyimpan informasi lain yang terkait dengan Classroom
tidak akurat atau tidak sesuai. Untuk menyiapkan database H2, Anda harus menambahkan hal berikut
konfigurasi ke application.properties
.
# Enable configuration for persistent storage using an H2 database
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:file:./h2/userdb
spring.datasource.username=<USERNAME>
spring.datasource.password=<PASSWORD>
spring.jpa.hibernate.ddl-auto=update
spring.jpa.open-in-view=false
Konfigurasi spring.datasource.url
membuat direktori, yang disebut h2
, dengan
file userdb
yang disimpan di dalamnya. Tambahkan jalur ke database H2 untuk
.gitignore
. Anda harus memperbarui spring.datasource.username
dan
spring.datasource.password
sebelum Anda menjalankan aplikasi untuk menyetel
{i>database <i}dengan nama pengguna
dan {i>password<i} pilihan Anda. Untuk memperbarui
nama pengguna dan {i>password<i} untuk {i>database<i}
setelah menjalankan aplikasi,
menghapus direktori h2
yang dihasilkan, memperbarui konfigurasi, dan
menjalankan kembali aplikasi.
Menyetel konfigurasi spring.jpa.hibernate.ddl-auto
ke update
akan memastikan bahwa
data yang tersimpan dalam database dipertahankan ketika aplikasi dimulai ulang.
Untuk menghapus database setiap kali aplikasi dimulai ulang, setel parameter ini
konfigurasi ke create
.
Tetapkan konfigurasi spring.jpa.open-in-view
ke false
. Konfigurasi ini diaktifkan
secara {i>default<i} dan dapat diketahui
mengakibatkan masalah kinerja yang
sulit didiagnosis dalam produksi.
Seperti dijelaskan sebelumnya, Anda harus dapat
mengambil kredensial suatu
pengguna berulang. Hal ini difasilitasi oleh penyimpanan kredensial bawaan
dukungan yang ditawarkan oleh GoogleAuthorizationCodeFlow
.
Di class AuthService.java
, tentukan jalur ke file tempat
kredensial yang disimpan. Dalam contoh ini, file dibuat di
Direktori /credentialStore
. Tambahkan jalur ke penyimpanan kredensial ke
.gitignore
. Direktori ini dibuat setelah pengguna memulai
alur otorisasi.
private static final File dataDirectory = new File("credentialStore");
Selanjutnya, buat metode dalam file AuthService.java
yang membuat dan
akan menampilkan objek FileDataStoreFactory
. Ini adalah {i>datastore<i} yang
menyimpan kredensial.
/** Creates and returns FileDataStoreFactory object to store credentials.
* @return FileDataStoreFactory dataStore used to save and obtain users ids
* mapped to Credentials.
* @throws IOException if creating the dataStore is unsuccessful.
*/
public FileDataStoreFactory getCredentialDataStore() throws IOException {
FileDataStoreFactory dataStore = new FileDataStoreFactory(dataDirectory);
return dataStore;
}
Perbarui metode getFlow()
di AuthService.java
untuk disertakan
setDataStoreFactory
di GoogleAuthorizationCodeFlow Builder()
dan memanggil getCredentialDataStore()
untuk menetapkan datastore.
GoogleAuthorizationCodeFlow authorizationCodeFlow =
new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT,
JSON_FACTORY,
getClientSecrets(),
getScopes())
.setAccessType("offline")
.setDataStoreFactory(getCredentialDataStore())
.build();
Selanjutnya, perbarui metode getAndSaveCredentials(String authorizationCode)
.
Sebelumnya, metode ini memperoleh kredensial tanpa menyimpannya
di mana saja. Memperbarui metode untuk menyimpan kredensial di datastore
diindeks oleh User-ID.
ID pengguna dapat diperoleh dari objek TokenResponse
menggunakan
id_token
, tetapi harus diverifikasi terlebih dahulu. Jika tidak, klien
aplikasi mungkin dapat meniru identitas pengguna dengan mengirim pengguna yang dimodifikasi
ID ke server. Anda sebaiknya menggunakan Google API Client
library untuk memvalidasi id_token
. Lihat [halaman Identitas Google di
memverifikasi token ID Google] untuk informasi lebih lanjut.
// Obtaining the id_token will help determine which user signed in to the application.
String idTokenString = tokenResponse.get("id_token").toString();
// Validate the id_token using the GoogleIdTokenVerifier object.
GoogleIdTokenVerifier googleIdTokenVerifier = new GoogleIdTokenVerifier.Builder(
HTTP_TRANSPORT,
JSON_FACTORY)
.setAudience(Collections.singletonList(
googleClientSecrets.getWeb().getClientId()))
.build();
GoogleIdToken idToken = googleIdTokenVerifier.verify(idTokenString);
if (idToken == null) {
throw new Exception("Invalid ID token.");
}
Setelah id_token
diverifikasi, dapatkan userId
untuk disimpan bersama
dengan kredensial yang diperoleh.
// Obtain the user id from the id_token.
Payload payload = idToken.getPayload();
String userId = payload.getSubject();
Update panggilan ke flow.createAndStoreCredential
untuk menyertakan userId
.
// Save the user id and credentials to the configured FileDataStoreFactory.
Credential credential = flow.createAndStoreCredential(tokenResponse, userId);
Tambahkan metode ke class AuthService.java
yang menampilkan kredensial
untuk pengguna tertentu jika ada di datastore.
/** Find credentials in the datastore based on a specific user id.
* @param userId key to find in the file datastore.
* @return Credential object to be returned if a matching key is found in the datastore. Null if
* the key doesn't exist.
* @throws Exception if building flow object or checking for userId key is unsuccessful. */
public Credential loadFromCredentialDataStore(String userId) throws Exception {
try {
GoogleAuthorizationCodeFlow flow = getFlow();
Credential credential = flow.loadCredential(userId);
return credential;
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
Mengambil kredensial
Tentukan metode untuk mengambil Users
. Anda akan mendapatkan id
di
Parameter kueri login_hint
, yang dapat Anda gunakan untuk mengambil pengguna tertentu
data.
Python
def get_credentials_from_storage(id):
"""
Retrieves credentials from the storage and returns them as a dictionary.
"""
return User.query.get(id)
Java
Di class AuthController.java
, tentukan metode untuk mengambil pengguna
{i>database<i} berdasarkan ID pengguna mereka.
/** Retrieves stored credentials based on the user id.
* @param id the id of the current user
* @return User the database entry corresponding to the current user or null
* if the user doesn't exist in the database.
*/
public User getUser(String id) {
if (id != null) {
Optional<User> user = userRepository.findById(id);
if (user.isPresent()) {
return user.get();
}
}
return null;
}
Simpan kredensial
Ada dua skenario saat menyimpan kredensial. Jika id
pengguna sudah
dalam {i>database<i}, lalu memperbarui {i>record
<i}yang ada dengan nilai baru. Jika tidak,
buat data User
baru dan tambahkan ke database.
Python
Pertama-tama, tentukan metode utilitas yang mengimplementasikan penyimpanan atau pembaruan perilaku model.
def save_user_credentials(credentials=None, user_info=None):
"""
Updates or adds a User to the database. A new user is added only if both
credentials and user_info are provided.
Args:
credentials: An optional Credentials object.
user_info: An optional dict containing user info returned by the
OAuth 2.0 API.
"""
existing_user = get_credentials_from_storage(
flask.session.get("login_hint"))
if existing_user:
if user_info:
existing_user.id = user_info.get("id")
existing_user.display_name = user_info.get("name")
existing_user.email = user_info.get("email")
existing_user.portrait_url = user_info.get("picture")
if credentials and credentials.refresh_token is not None:
existing_user.refresh_token = credentials.refresh_token
elif credentials and user_info:
new_user = User(id=user_info.get("id"),
display_name=user_info.get("name"),
email=user_info.get("email"),
portrait_url=user_info.get("picture"),
refresh_token=credentials.refresh_token)
db.session.add(new_user)
db.session.commit()
Ada dua contoh di mana Anda mungkin
menyimpan kredensial ke
database: saat pengguna kembali ke aplikasi Anda di akhir metode
alur otorisasi dan saat mengeluarkan panggilan API. Di sinilah kita
sebelumnya sudah menyetel
kunci credentials
sesi.
Panggil save_user_credentials
di akhir rute callback
Anda. Tetap
user_info
, bukan hanya mengekstrak nama pengguna.
# The flow is complete! We'll use the credentials to fetch the user's info.
user_info_service = googleapiclient.discovery.build(
serviceName="oauth2", version="v2", credentials=credentials)
user_info = user_info_service.userinfo().get().execute()
flask.session["username"] = user_info.get("name")
save_user_credentials(credentials, user_info)
Anda juga harus memperbarui kredensial setelah panggilan ke API. Di sini
kasus ini, Anda dapat memberikan kredensial yang diperbarui sebagai argumen
Metode save_user_credentials
.
# Save credentials in case access token was refreshed.
flask.session["credentials"] = credentials_to_dict(credentials)
save_user_credentials(credentials)
Java
Pertama-tama, tentukan metode yang menyimpan atau memperbarui objek User
di H2
di skrip untuk menyiapkan database.
/** Adds or updates a user in the database.
* @param credential the credentials object to save or update in the database.
* @param userinfo the userinfo object to save or update in the database.
* @param session the current session.
*/
public void saveUser(Credential credential, Userinfo userinfo, HttpSession session) {
User storedUser = null;
if (session != null && session.getAttribute("login_hint") != null) {
storedUser = getUser(session.getAttribute("login_hint").toString());
}
if (storedUser != null) {
if (userinfo != null) {
storedUser.setId(userinfo.getId());
storedUser.setEmail(userinfo.getEmail());
}
userRepository.save(storedUser);
} else if (credential != null && userinfo != null) {
User newUser = new User(
userinfo.getId(),
userinfo.getEmail(),
);
userRepository.save(newUser);
}
}
Ada dua contoh di mana Anda mungkin
menyimpan kredensial ke
database: saat pengguna kembali ke aplikasi Anda di akhir metode
alur otorisasi dan saat mengeluarkan panggilan API. Di sinilah kita
sebelumnya sudah menyetel
kunci credentials
sesi.
Panggil saveUser
di akhir rute /callback
. Anda harus tetap mempertahankan
user_info
, bukan hanya mengekstrak email pengguna.
/** This is the end of the auth flow. We should save user info to the database. */
Userinfo userinfo = authService.getUserInfo(credentials);
saveUser(credentials, userinfo, session);
Anda juga harus memperbarui kredensial setelah panggilan ke API. Di sini
ini, Anda dapat memberikan kredensial yang diperbarui sebagai argumen ke saveUser
.
/** Save credentials in case access token was refreshed. */
saveUser(credentials, null, session);
Kredensial sudah tidak berlaku
Perhatikan bahwa ada beberapa alasan mengapa token refresh bisa menjadi tidak valid. Ini termasuk:
- Token refresh tidak digunakan selama enam bulan.
- Pengguna mencabut izin akses aplikasi Anda.
- Pengguna mengubah sandi.
- Pengguna merupakan anggota organisasi Google Cloud yang memiliki kontrol sesi kebijakan yang berlaku.
Memperoleh token baru dengan mengirimkan pengguna melalui alur otorisasi lagi jika kredensial mereka menjadi tidak valid.
Mengarahkan pengguna secara otomatis
Mengubah rute landing add-on untuk mendeteksi apakah pengguna telah mengizinkan sebelumnya aplikasi kita. Jika ya, arahkan mereka ke halaman add-on utama kami. Jika tidak, dialogkan mereka untuk masuk.
Python
Memastikan file database telah dibuat saat aplikasi
peluncuran. Masukkan kode berikut ke dalam penginisialisasi modul (seperti
webapp/__init__.py
dalam contoh yang kami berikan) atau dalam metode utama yang
meluncurkan server.
# Initialize the database file if not created.
if not os.path.exists(DATABASE_FILE_NAME):
db.create_all()
Metode Anda kemudian harus menangani parameter kueri login_hint
sebagai
yang dibahas di atas. Kemudian, muat kredensial toko jika ini adalah pengulangan
pengunjung. Anda mengetahui bahwa pengunjung adalah pengunjung berulang jika menerima login_hint
.
Ambil kredensial yang tersimpan untuk pengguna ini dan muat ke dalam
sesi.
stored_credentials = get_credentials_from_storage(login_hint)
# If we have stored credentials, store them in the session.
if stored_credentials:
# Load the client secrets file contents.
client_secrets_dict = json.load(
open(CLIENT_SECRETS_FILE)).get("web")
# Update the credentials in the session.
if not flask.session.get("credentials"):
flask.session["credentials"] = {}
flask.session["credentials"] = {
"token": stored_credentials.access_token,
"refresh_token": stored_credentials.refresh_token,
"token_uri": client_secrets_dict["token_uri"],
"client_id": client_secrets_dict["client_id"],
"client_secret": client_secrets_dict["client_secret"],
"scopes": SCOPES
}
# Set the username in the session.
flask.session["username"] = stored_credentials.display_name
Terakhir, arahkan pengguna ke halaman {i>sign in<i} jika kita tidak memiliki memiliki kredensial yang lengkap. Jika kami melakukannya, arahkan mereka ke halaman add-on utama.
if "credentials" not in flask.session or \
flask.session["credentials"]["refresh_token"] is None:
return flask.render_template("authorization.html")
return flask.render_template(
"addon-discovery.html",
message="You've reached the addon discovery page.")
Java
Buka rute landing add-on Anda (/addon-discovery
di kolom yang disediakan
contoh). Seperti yang dibahas di atas, di sinilah Anda menangani login_hint
parameter kueri.
Pertama, periksa apakah ada kredensial dalam sesi tersebut. Jika tidak, arahkan rute
pengguna melalui alur autentikasi dengan memanggil metode startAuthFlow
.
/** Check if the credentials exist in the session. The session could have
* been cleared when the user clicked the Sign-Out button, and the expected
* behavior after sign-out would be to display the sign-in page when the
* iframe is opened again. */
if (session.getAttribute("credentials") == null) {
return startAuthFlow(model);
}
Kemudian, muat pengguna dari database H2 jika ini adalah pengunjung berulang. Penting
pengunjung berulang jika Anda menerima parameter kueri login_hint
. Jika
ada di database H2, muat kredensial dari kredensial
yang telah disiapkan sebelumnya, lalu tetapkan kredensial dalam sesi tersebut. Jika
kredensial tidak diperoleh dari datastore kredensial, arahkan pengguna
melalui alur autentikasi dengan memanggil startAuthFlow
.
/** At this point, we know that credentials exist in the session, but we
* should update the session credentials with the credentials in persistent
* storage in case they were refreshed. If the credentials in persistent
* storage are null, we should navigate the user to the authorization flow
* to obtain persisted credentials. */
User storedUser = getUser(login_hint);
if (storedUser != null) {
Credential credential = authService.loadFromCredentialDataStore(login_hint);
if (credential != null) {
session.setAttribute("credentials", credential);
} else {
return startAuthFlow(model);
}
}
Terakhir, arahkan pengguna ke halaman landing add-on.
/** Finally, if there are credentials in the session and in persistent
* storage, direct the user to the addon-discovery page. */
return "addon-discovery";
Menguji add-on
Login ke Google Classroom sebagai salah satu ujian Pengajar Anda pelanggan. Pilih tab Tugas Kelas dan buat Tugas baru. Klik tombol Add-on di bawah area teks, lalu pilih add-on Anda. iframe terbuka dan add-on akan memuat URI Penyiapan Lampiran yang Anda tentukan di Halaman Konfigurasi Aplikasi Google Workspace Marketplace SDK.
Selamat! Anda siap untuk melanjutkan ke langkah berikutnya: membuat lampiran dan mengidentifikasi peran pengguna.