Nutzer anmelden

Dies ist die zweite Anleitung in der Reihe zu Classroom-Add‑ons.

In dieser Anleitung fügen Sie der Webanwendung die Google-Anmeldung hinzu. Dies ist ein erforderliches Verhalten für Classroom-Add‑ons. Verwenden Sie die Anmeldedaten aus diesem Autorisierungsablauf für alle zukünftigen Aufrufe der API.

Im Laufe dieser Anleitung führen Sie folgende Schritte aus:

  • Konfigurieren Sie Ihre Webanwendung so, dass Sitzungsdaten in einem iFrame gespeichert werden.
  • Implementieren Sie den serverseitigen Google OAuth 2.0-Anmeldeablauf.
  • Führen Sie einen Aufruf an die OAuth 2.0 API aus.
  • Erstellen Sie zusätzliche Routen, um Autorisierungen, Abmeldungen und API-Aufrufe zu testen.

Anschließend können Sie Nutzer in Ihrer Webanwendung vollständig autorisieren und Aufrufe an Google APIs senden.

Autorisierungsablauf

Google APIs verwenden zur Authentifizierung und Autorisierung das OAuth 2.0-Protokoll. Eine vollständige Beschreibung der OAuth-Implementierung von Google finden Sie im OAuth-Leitfaden von Google Identity.

Die Anmeldedaten Ihrer Anwendung werden in Google Cloud verwaltet. Nachdem sie erstellt wurden, implementieren Sie einen vierstufigen Prozess, um einen Nutzer zu authentifizieren und zu autorisieren:

  1. Autorisierung anfordern. Geben Sie im Rahmen dieser Anfrage eine Callback-URL an. Nach Abschluss erhalten Sie eine Autorisierungs-URL.
  2. Leiten Sie den Nutzer zur Autorisierungs-URL weiter. Auf der resultierenden Seite werden dem Nutzer die Berechtigungen angezeigt, die Ihre App benötigt, und er wird aufgefordert, den Zugriff zu erlauben. Nach Abschluss wird der Nutzer zur Callback-URL weitergeleitet.
  3. Sie erhalten einen Autorisierungscode über Ihre Callback-Route. Tauschen Sie den Autorisierungscode gegen ein Zugriffstoken und ein Aktualisierungstoken ein.
  4. Senden Sie mit den Tokens Aufrufe an eine Google API.

OAuth 2.0-Anmeldedaten abrufen

Achten Sie darauf, dass Sie OAuth-Anmeldedaten wie auf der Übersichtsseite beschrieben erstellt und heruntergeladen haben. Ihr Projekt muss diese Anmeldedaten verwenden, um den Nutzer anzumelden.

Autorisierungsablauf implementieren

Fügen Sie unserer Webanwendung Logik und Routen hinzu, um den beschriebenen Ablauf zu realisieren, einschließlich der folgenden Funktionen:

  • Autorisierungsablauf nach dem Aufrufen der Landingpage initiieren.
  • Autorisierung anfordern und die Antwort des Autorisierungsservers verarbeiten.
  • Gespeicherte Anmeldedaten löschen.
  • Berechtigungen der App widerrufen.
  • API-Aufruf testen.

Autorisierung initiieren

Ändern Sie bei Bedarf Ihre Landingpage, um den Autorisierungsablauf zu initiieren. Das Add‑on kann sich in zwei möglichen Zuständen befinden: Entweder sind in der aktuellen Sitzung Tokens gespeichert oder Sie müssen Tokens vom OAuth 2.0-Server abrufen. Führen Sie einen Test-API-Aufruf aus, wenn Tokens in der Sitzung vorhanden sind, oder fordern Sie den Nutzer andernfalls auf, sich anzumelden.

Python

Öffnen Sie die Datei routes.py. Legen Sie zuerst einige Konstanten und unsere Cookie Konfiguration gemäß den Empfehlungen zur iFrame-Sicherheit fest.

# The file that contains the OAuth 2.0 client_id and client_secret.
CLIENT_SECRETS_FILE = "client_secret.json"

# The OAuth 2.0 access scopes to request.
# These scopes must match the scopes in your Google Cloud project's OAuth Consent
# Screen: https://console.cloud.google.com/apis/credentials/consent
SCOPES = [
    "openid",
    "https://www.googleapis.com/auth/userinfo.profile",
    "https://www.googleapis.com/auth/userinfo.email",
    "https://www.googleapis.com/auth/classroom.addons.teacher",
    "https://www.googleapis.com/auth/classroom.addons.student"
]

# Flask cookie configurations.
app.config.update(
    SESSION_COOKIE_SECURE=True,
    SESSION_COOKIE_HTTPONLY=True,
    SESSION_COOKIE_SAMESITE="None",
)

Gehen Sie zur Landingroute Ihres Add‑ons (in der Beispieldatei /classroom-addon). Fügen Sie Logik hinzu, um eine Anmeldeseite zu rendern, wenn die Sitzung den Schlüssel „credentials“ nicht enthält.

@app.route("/classroom-addon")
def classroom_addon():
    if "credentials" not in flask.session:
        return flask.render_template("authorization.html")

    return flask.render_template(
        "addon-discovery.html",
        message="You've reached the addon discovery page.")

Java

Der Code für diese Anleitung befindet sich im Modul step_02_sign_in.

Öffnen Sie die Datei application.properties und fügen Sie eine Sitzungskonfiguration hinzu, die den Empfehlungen zur iFrame-Sicherheit entspricht.

# iFrame security recommendations call for cookies to have the HttpOnly and
# secure attribute set
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true

# Ensures that the session is maintained across the iframe and sign-in pop-up.
server.servlet.session.cookie.same-site=none

Erstellen Sie eine Dienstklasse (AuthService.java im Modul step_02_sign_in), um die Logik hinter den Endpunkten in der Controllerdatei zu verarbeiten und die Weiterleitungs-URI, den Speicherort der Datei mit den Client-Secrets und die Bereiche einzurichten, die Ihr Add‑on benötigt. Die Weiterleitungs-URI wird verwendet, um Ihre Nutzer nach der Autorisierung Ihrer App zu einer bestimmten URI weiterzuleiten. Informationen zum Speicherort der Datei client_secret.json finden Sie im Abschnitt „Project Set Up“ (Projekteinrichtung) der Datei README.md im Quellcode.

@Service
public class AuthService {
    private static final String REDIRECT_URI = "https://localhost:5000/callback";
    private static final String CLIENT_SECRET_FILE = "client_secret.json";
    private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
    private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();

    private static final String[] REQUIRED_SCOPES = {
        "https://www.googleapis.com/auth/userinfo.profile",
        "https://www.googleapis.com/auth/userinfo.email",
        "https://www.googleapis.com/auth/classroom.addons.teacher",
        "https://www.googleapis.com/auth/classroom.addons.student"
    };

    /** Creates and returns a Collection object with all requested scopes.
    *   @return Collection of scopes requested by the application.
    */
    public static Collection<String> getScopes() {
        return new ArrayList<>(Arrays.asList(REQUIRED_SCOPES));
    }
}

Öffnen Sie die Controllerdatei (AuthController.java im step_02_sign_in Modul) und fügen Sie der Landingroute Logik hinzu, um die Anmeldeseite zu rendern, wenn die Sitzung den Schlüssel credentials nicht enthält.

@GetMapping(value = {"/start-auth-flow"})
public String startAuthFlow(Model model) {
    try {
        return "authorization";
    } catch (Exception e) {
        return onError(e.getMessage(), model);
    }
}

@GetMapping(value = {"/addon-discovery"})
public String addon_discovery(HttpSession session, Model model) {
    try {
        if (session == null || session.getAttribute("credentials") == null) {
            return startAuthFlow(model);
        }
        return "addon-discovery";
    } catch (Exception e) {
        return onError(e.getMessage(), model);
    }
}

Ihre Autorisierungsseite sollte einen Link oder eine Schaltfläche enthalten, über die sich der Nutzer anmelden kann. Wenn der Nutzer darauf klickt, sollte er zur Route authorize weitergeleitet werden.

Autorisierung anfordern

Um eine Autorisierung anzufordern, erstellen Sie eine Authentifizierungs-URL und leiten Sie den Nutzer dorthin weiter. Diese URL enthält verschiedene Informationen, z. B. die angeforderten Bereiche, die Zielroute nach der Autorisierung und die Client-ID der Webanwendung. Sie können diese in dieser Beispiel-Autorisierungs-URL sehen.

Python

Fügen Sie der Datei routes.py den folgenden Import hinzu.

import google_auth_oauthlib.flow

Erstellen Sie eine neue Route /authorize. Erstellen Sie eine Instanz von google_auth_oauthlib.flow.Flow. Wir empfehlen dringend, dazu die enthaltene Methode from_client_secrets_file zu verwenden.

@app.route("/authorize")
def authorize():
    # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow
    # steps.
    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
        CLIENT_SECRETS_FILE, scopes=SCOPES)

Legen Sie die redirect_uri des flow fest. Dies ist die Route, zu der Nutzer nach der Autorisierung Ihrer App zurückkehren sollen. Im folgenden Beispiel ist das /callback.

# The URI created here must exactly match one of the authorized redirect
# URIs for the OAuth 2.0 client, which you configured in the API Console. If
# this value doesn't match an authorized URI, you will get a
# "redirect_uri_mismatch" error.
flow.redirect_uri = flask.url_for("callback", _external=True)

Verwenden Sie das Flow-Objekt, um die authorization_url und den state zu erstellen. Speichern Sie den state in der Sitzung. Er wird später verwendet, um die Authentizität der Serverantwort zu überprüfen. Leiten Sie den Nutzer schließlich zur authorization_url weiter.

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")

# Store the state so the callback can verify the auth server response.
flask.session["state"] = state

# Redirect the user to the OAuth authorization URL.
return flask.redirect(authorization_url)

Java

Fügen Sie der Datei AuthService.java die folgenden Methoden hinzu, um das Flow-Objekt zu instanziieren und dann die Autorisierungs-URL abzurufen:

  • Die Methode getClientSecrets() liest die Datei mit den Client-Secrets und erstellt ein GoogleClientSecrets-Objekt.
  • Die Methode getFlow() erstellt eine Instanz von GoogleAuthorizationCodeFlow.
  • Die Methode authorize() verwendet das GoogleAuthorizationCodeFlow-Objekt, den Parameter state und die Weiterleitungs-URI, um die Autorisierungs-URL abzurufen. Der Parameter state wird verwendet, um die Authentizität der Antwort vom Autorisierungsserver zu überprüfen. Die Methode gibt dann eine Zuordnung mit der Autorisierungs-URL und dem Parameter state zurück.
/** Reads the client secret file downloaded from Google Cloud.
 *   @return GoogleClientSecrets read in from client secret file. */
public GoogleClientSecrets getClientSecrets() throws Exception {
    try {
        InputStream in = SignInApplication.class.getClassLoader()
            .getResourceAsStream(CLIENT_SECRET_FILE);
        if (in == null) {
            throw new FileNotFoundException("Client secret file not found: "
                +   CLIENT_SECRET_FILE);
        }
        GoogleClientSecrets clientSecrets = GoogleClientSecrets
            .load(JSON_FACTORY, new InputStreamReader(in));
        return clientSecrets;
    } catch (Exception e) {
        throw e;
    }
}

/** Builds and returns authorization code flow.
*   @return GoogleAuthorizationCodeFlow object used to retrieve an access
*   token and refresh token for the application.
*   @throws Exception if reading client secrets or building code flow object
*   is unsuccessful.
*/
public GoogleAuthorizationCodeFlow getFlow() throws Exception {
    try {
        GoogleAuthorizationCodeFlow authorizationCodeFlow =
            new GoogleAuthorizationCodeFlow.Builder(
                HTTP_TRANSPORT,
                JSON_FACTORY,
                getClientSecrets(),
                getScopes())
                .setAccessType("offline")
                .build();
        return authorizationCodeFlow;
    } catch (Exception e) {
        throw e;
    }
}

/** Builds and returns a map with the authorization URL, which allows the
*   user to give the app permission to their account, and the state parameter,
*   which is used to prevent cross site request forgery.
*   @return map with authorization URL and state parameter.
*   @throws Exception if building the authorization URL is unsuccessful.
*/
public HashMap authorize() throws Exception {
    HashMap<String, String> authDataMap = new HashMap<>();
    try {
        String state = new BigInteger(130, new SecureRandom()).toString(32);
        authDataMap.put("state", state);

        GoogleAuthorizationCodeFlow flow = getFlow();
        String authUrl = flow
            .newAuthorizationUrl()
            .setState(state)
            .setRedirectUri(REDIRECT_URI)
            .build();
        String url = authUrl;
        authDataMap.put("url", url);

        return authDataMap;
    } catch (Exception e) {
        throw e;
    }
}

Verwenden Sie die Konstruktor-Injection, um eine Instanz der Dienstklasse in der Controllerklasse zu erstellen.

/** Declare AuthService to be used in the Controller class constructor. */
private final AuthService authService;

/** AuthController constructor. Uses constructor injection to instantiate
*   the AuthService and UserRepository classes.
*   @param authService the service class that handles the implementation logic
*   of requests.
*/
public AuthController(AuthService authService) {
    this.authService = authService;
}

Fügen Sie der Controllerklasse den Endpunkt /authorize hinzu. Dieser Endpunkt ruft die Methode authorize() von AuthService auf, um den Parameter state und die Autorisierungs-URL abzurufen. Anschließend speichert der Endpunkt den state Parameter in der Sitzung und leitet die Nutzer zur Autorisierungs-URL weiter.

/** Redirects the sign-in pop-up to the authorization URL.
*   @param response the current response to pass information to.
*   @param session the current session.
*   @throws Exception if redirection to the authorization URL is unsuccessful.
*/
@GetMapping(value = {"/authorize"})
public void authorize(HttpServletResponse response, HttpSession session)
    throws Exception {
    try {
        HashMap authDataMap = authService.authorize();
        String authUrl = authDataMap.get("url").toString();
        String state = authDataMap.get("state").toString();
        session.setAttribute("state", state);
        response.sendRedirect(authUrl);
    } catch (Exception e) {
        throw e;
    }
}

Serverantwort verarbeiten

Nach der Autorisierung kehrt der Nutzer zur Route redirect_uri aus dem vorherigen Schritt zurück. Im vorherigen Beispiel ist diese Route /callback.

Sie erhalten einen code in der Antwort, wenn der Nutzer von der Autorisierungsseite zurückkehrt. Tauschen Sie den Code dann gegen Zugriffs- und Aktualisierungstokens ein:

Python

Fügen Sie der Flask-Serverdatei die folgenden Importe hinzu.

import google.oauth2.credentials
import googleapiclient.discovery

Fügen Sie die Route Ihrem Server hinzu. Erstellen Sie eine weitere Instanz von google_auth_oauthlib.flow.Flow, verwenden Sie aber dieses Mal den im vorherigen Schritt gespeicherten Status.

@app.route("/callback")
def callback():
    state = flask.session["state"]

    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
        CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
    flow.redirect_uri = flask.url_for("callback", _external=True)

Fordern Sie als Nächstes Zugriffs- und Aktualisierungstokens an. Glücklicherweise enthält das flow-Objekt auch die Methode fetch_token, um dies zu erreichen. Die Methode erwartet entweder die code oder authorization_response Argumente. Verwenden Sie authorization_response, da es sich um die vollständige URL aus der Anfrage handelt.

authorization_response = flask.request.url
flow.fetch_token(authorization_response=authorization_response)

Sie haben jetzt vollständige Anmeldedaten. Speichern Sie sie in der Sitzung, damit sie in anderen Methoden oder Routen abgerufen werden können, und leiten Sie dann zu einer Landingpage für Add‑ons weiter.

credentials = flow.credentials
flask.session["credentials"] = {
    "token": credentials.token,
    "refresh_token": credentials.refresh_token,
    "token_uri": credentials.token_uri,
    "client_id": credentials.client_id,
    "client_secret": credentials.client_secret,
    "scopes": credentials.scopes
}

# Close the pop-up by rendering an HTML page with a script that redirects
# the owner and closes itself. This can be done with a bit of JavaScript:
# <script>
#     window.opener.location.href = "{{ url_for('classroom_addon') }}";
#     window.close();
# </script>
return flask.render_template("close-me.html")

Java

Fügen Sie Ihrer Dienstklasse eine Methode hinzu, die das Credentials-Objekt zurückgibt, indem Sie den Autorisierungscode übergeben, der aus der Weiterleitung durch die Autorisierungs-URL abgerufen wurde. Dieses Credentials-Objekt wird später verwendet, um das Zugriffstoken und das Aktualisierungstoken abzurufen.

/** Returns the required credentials to access Google APIs.
*   @param authorizationCode the authorization code provided by the
*   authorization URL that's used to obtain credentials.
*   @return the credentials that were retrieved from the authorization flow.
*   @throws Exception if retrieving credentials is unsuccessful.
*/
public Credential getAndSaveCredentials(String authorizationCode) throws Exception {
    try {
        GoogleAuthorizationCodeFlow flow = getFlow();
        GoogleClientSecrets googleClientSecrets = getClientSecrets();
        TokenResponse tokenResponse = flow.newTokenRequest(authorizationCode)
            .setClientAuthentication(new ClientParametersAuthentication(
                googleClientSecrets.getWeb().getClientId(),
                googleClientSecrets.getWeb().getClientSecret()))
            .setRedirectUri(REDIRECT_URI)
            .execute();
        Credential credential = flow.createAndStoreCredential(tokenResponse, null);
        return credential;
    } catch (Exception e) {
        throw e;
    }
}

Fügen Sie dem Controller einen Endpunkt für Ihre Weiterleitungs-URI hinzu. Rufen Sie den Autorisierungscode und den Parameter state aus der Anfrage ab. Vergleichen Sie diesen Parameter state mit dem Attribut state, das in der Sitzung gespeichert ist. Wenn sie übereinstimmen, fahren Sie mit dem Autorisierungsablauf fort. Wenn sie nicht übereinstimmen, geben Sie einen Fehler zurück.

Rufen Sie dann die Methode getAndSaveCredentials von AuthService auf und übergeben Sie den Autorisierungscode als Parameter. Nachdem Sie das Credentials-Objekt abgerufen haben, speichern Sie es in der Sitzung. Schließen Sie dann das Dialogfeld und leiten Sie den Nutzer zur Landingpage für Add‑ons weiter.

/** Handles the redirect URL to grant the application access to the user's
*   account.
*   @param request the current request used to obtain the authorization code
*   and state parameter from.
*   @param session the current session.
*   @param response the current response to pass information to.
*   @param model the Model interface to pass error information that's
*   displayed on the error page.
*   @return the close-pop-up template if authorization is successful, or the
*   onError method to handle and display the error message.
*/
@GetMapping(value = {"/callback"})
public String callback(HttpServletRequest request, HttpSession session,
    HttpServletResponse response, Model model) {
    try {
        String authCode = request.getParameter("code");
        String requestState = request.getParameter("state");
        String sessionState = session.getAttribute("state").toString();
        if (!requestState.equals(sessionState)) {
            response.setStatus(401);
            return onError("Invalid state parameter.", model);
        }
        Credential credentials = authService.getAndSaveCredentials(authCode);
        session.setAttribute("credentials", credentials);
        return "close-pop-up";
    } catch (Exception e) {
        return onError(e.getMessage(), model);
    }
}

API-Aufruf testen

Nach Abschluss des Ablaufs können Sie jetzt Aufrufe an Google APIs senden.

Fordern Sie beispielsweise die Profilinformationen des Nutzers an. Sie können die Informationen des Nutzers von der OAuth 2.0 API anfordern.

Python

Lesen Sie die Dokumentation zur OAuth 2.0 Discovery API Verwenden Sie sie, um ein ausgefülltes UserInfo-Objekt abzurufen.

# Retrieve the credentials from the session data and construct a
# Credentials instance.
credentials = google.oauth2.credentials.Credentials(
    **flask.session["credentials"])

# Construct the OAuth 2.0 v2 discovery API library.
user_info_service = googleapiclient.discovery.build(
    serviceName="oauth2", version="v2", credentials=credentials)

# Request and store the username in the session.
# This allows it to be used in other methods or in an HTML template.
flask.session["username"] = (
    user_info_service.userinfo().get().execute().get("name"))

Java

Erstellen Sie in der Dienstklasse eine Methode, die ein UserInfo-Objekt mit den Credentials als Parameter erstellt.

/** Obtains the Userinfo object by passing in the required credentials.
*   @param credentials retrieved from the authorization flow.
*   @return the Userinfo object for the currently signed-in user.
*   @throws IOException if creating UserInfo service or obtaining the
*   Userinfo object is unsuccessful.
*/
public Userinfo getUserInfo(Credential credentials) throws IOException {
    try {
        Oauth2 userInfoService = new Oauth2.Builder(
            new NetHttpTransport(),
            new GsonFactory(),
            credentials).build();
        Userinfo userinfo = userInfoService.userinfo().get().execute();
        return userinfo;
    } catch (Exception e) {
        throw e;
    }
}

Fügen Sie dem Controller den Endpunkt /test hinzu, der die E‑Mail-Adresse des Nutzers anzeigt.

/** Returns the test request page with the user's email.
*   @param session the current session.
*   @param model the Model interface to pass error information that's
*   displayed on the error page.
*   @return the test page that displays the current user's email or the
*   onError method to handle and display the error message.
*/
@GetMapping(value = {"/test"})
public String test(HttpSession session, Model model) {
    try {
        Credential credentials = (Credential) session.getAttribute("credentials");
        Userinfo userInfo = authService.getUserInfo(credentials);
        String userInfoEmail = userInfo.getEmail();
        if (userInfoEmail != null) {
            model.addAttribute("userEmail", userInfoEmail);
        } else {
            return onError("Could not get user email.", model);
        }
        return "test";
    } catch (Exception e) {
        return onError(e.getMessage(), model);
    }
}

Anmeldedaten löschen

Sie können die Anmeldedaten eines Nutzers „löschen“, indem Sie sie aus der aktuellen Sitzung entfernen. So können Sie das Routing auf der Landingpage für Add‑ons testen.

Wir empfehlen, anzugeben, dass sich der Nutzer abgemeldet hat, bevor Sie ihn zur Landingpage für Add‑ons weiterleiten. Ihre App sollte den Autorisierungsablauf durchlaufen, um neue Anmeldedaten abzurufen. Nutzer werden jedoch nicht aufgefordert, Ihre App noch einmal zu autorisieren.

Python

@app.route("/clear")
def clear_credentials():
    if "credentials" in flask.session:
        del flask.session["credentials"]
        del flask.session["username"]

    return flask.render_template("signed-out.html")

Alternativ können Sie flask.session.clear() verwenden. Dies kann jedoch unbeabsichtigte Auswirkungen haben, wenn andere Werte in der Sitzung gespeichert sind.

Java

Fügen Sie dem Controller einen Endpunkt /clear hinzu.

/** Clears the credentials in the session and returns the sign-out
*   confirmation page.
*   @param session the current session.
*   @return the sign-out confirmation page.
*/
@GetMapping(value = {"/clear"})
public String clear(HttpSession session) {
    try {
        if (session != null && session.getAttribute("credentials") != null) {
            session.removeAttribute("credentials");
        }
        return "sign-out";
    } catch (Exception e) {
        return onError(e.getMessage(), model);
    }
}

Berechtigung der App widerrufen

Ein Nutzer kann die Berechtigung Ihrer App widerrufen, indem er eine POST-Anfrage an https://oauth2.googleapis.com/revoke sendet. Die Anfrage sollte das Zugriffstoken des Nutzers enthalten.

Python

import requests

@app.route("/revoke")
def revoke():
    if "credentials" not in flask.session:
        return flask.render_template("addon-discovery.html",
                            message="You need to authorize before " +
                            "attempting to revoke credentials.")

    credentials = google.oauth2.credentials.Credentials(
        **flask.session["credentials"])

    revoke = requests.post(
        "https://oauth2.googleapis.com/revoke",
        params={"token": credentials.token},
        headers={"content-type": "application/x-www-form-urlencoded"})

    if "credentials" in flask.session:
        del flask.session["credentials"]
        del flask.session["username"]

    status_code = getattr(revoke, "status_code")
    if status_code == 200:
        return flask.render_template("authorization.html")
    else:
        return flask.render_template(
            "index.html", message="An error occurred during revocation!")

Java

Fügen Sie der Dienstklasse eine Methode hinzu, die einen Aufruf an den Endpunkt zum Widerrufen sendet.

/** Revokes the app's permissions to the user's account.
*   @param credentials retrieved from the authorization flow.
*   @return response entity returned from the HTTP call to obtain response
*   information.
*   @throws RestClientException if the POST request to the revoke endpoint is
*   unsuccessful.
*/
public ResponseEntity<String> revokeCredentials(Credential credentials) throws RestClientException {
    try {
        String accessToken = credentials.getAccessToken();
        String url = "https://oauth2.googleapis.com/revoke?token=" + accessToken;

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE);
        HttpEntity<Object> httpEntity = new HttpEntity<Object>(httpHeaders);
        ResponseEntity<String> responseEntity = new RestTemplate().exchange(
            url,
            HttpMethod.POST,
            httpEntity,
            String.class);
        return responseEntity;
    } catch (RestClientException e) {
        throw e;
    }
}

Fügen Sie dem Controller einen Endpunkt /revoke hinzu, der die Sitzung löscht und den Nutzer zur Autorisierungsseite weiterleitet, wenn der Widerruf erfolgreich war.

/** Revokes the app's permissions and returns the authorization page.
*   @param session the current session.
*   @return the authorization page.
*   @throws Exception if revoking access is unsuccessful.
*/
@GetMapping(value = {"/revoke"})
public String revoke(HttpSession session) throws Exception {
    try {
        if (session != null && session.getAttribute("credentials") != null) {
            Credential credentials = (Credential) session.getAttribute("credentials");
            ResponseEntity responseEntity = authService.revokeCredentials(credentials);
            Integer httpStatusCode = responseEntity.getStatusCodeValue();

            if (httpStatusCode != 200) {
                return onError("There was an issue revoking access: " +
                    responseEntity.getStatusCode(), model);
            }
            session.removeAttribute("credentials");
        }
        return startAuthFlow(model);
    } catch (Exception e) {
        return onError(e.getMessage(), model);
    }
}

Add‑on testen

Melden Sie sich in Google Classroom als einer Ihrer Lehrer Testnutzer an. Rufen Sie den Tab Kursaufgaben auf und erstellen Sie eine neue Aufgabe. Klicken Sie unter dem Textfeld auf die Schaltfläche Add‑ons und wählen Sie Ihr Add‑on aus. Der iFrame wird geöffnet und das Add‑on lädt die URI für die Einrichtung von Anhängen , die Sie auf der Seite „App Konfiguration“ des GWM SDK angegeben haben.

Glückwunsch! Sie können mit dem nächsten Schritt fortfahren: Umgang mit wiederholten Besuchen Ihres Add‑ons.