Kullanıcının oturumunu açın

Bu, Classroom eklentileri açıklamalı kılavuz serisinin ikinci bölümüdür.

Bu adım adım açıklamalı kılavuzda, web uygulamasına Google ile Oturum Açma özelliğini ekleyeceksiniz. Bu, Classroom eklentileri için zorunlu bir davranıştır. API'ye yapılacak gelecekteki tüm çağrılar için bu yetkilendirme akışında bulunan kimlik bilgilerini kullanın.

Bu adım adım açıklamalı kılavuzda şunları tamamlarsınız:

  • Web uygulamanızı, iFrame içindeki oturum verilerini koruyacak şekilde yapılandırın.
  • Google OAuth 2.0 sunucudan sunucuya oturum açma akışını uygulayın.
  • OAuth 2.0 API'ye bir çağrı gönderin.
  • API çağrılarının yetkilendirilmesini, oturumun kapatılmasını ve test edilmesini desteklemek için ek rotalar oluşturun.

Bu işlem tamamlandıktan sonra web uygulamanızdaki kullanıcıları tam olarak yetkilendirebilir ve Google API'lerine çağrı gönderebilirsiniz.

Yetkilendirme akışını anlama

Google API'leri, kimlik doğrulama ve yetkilendirme için OAuth 2.0 protokolünü kullanır. Google'ın OAuth uygulamasının tam açıklamasını Google Kimliği OAuth rehberinde bulabilirsiniz.

Uygulamanızın kimlik bilgileri Google Cloud'da yönetilir. Bunlar oluşturulduktan sonra, kullanıcının kimliğini doğrulamak ve yetkilendirmek için dört adımlı bir işlem uygulayın:

  1. Yetkilendirme isteyin. Bu istek kapsamında bir geri çağırma URL'si sağlayın. İşlem tamamlandığında bir yetkilendirme URL'si alırsınız.
  2. Kullanıcıyı yetkilendirme URL'sine yönlendirin. Açılan sayfada kullanıcı, uygulamanızın gerektirdiği izinler hakkında bilgilendirilir ve erişime izin vermesi istenir. İşlem tamamlandığında, kullanıcı geri çağırma URL'sine yönlendirilir.
  3. Geri çağırma rotanızda bir yetkilendirme kodu alın. Yetkilendirme kodunu erişim jetonu ve yenileme jetonuyla değiştirin.
  4. Jetonları kullanarak bir Google API'sine çağrı yapmak.

OAuth 2.0 kimlik bilgileri edinme

Genel bakış sayfasında açıklandığı şekilde OAuth kimlik bilgilerini oluşturup indirdiğinizden emin olun. Projeniz, kullanıcının oturum açması için bu kimlik bilgilerini kullanmalıdır.

Yetkilendirme akışını uygulama

Aşağıdaki özellikler de dahil olmak üzere açıklanan akışı gerçekleştirmek için web uygulamamıza mantık ve rotalar ekleyin:

  • Açılış sayfasına ulaşıldığında yetkilendirme akışını başlatın.
  • Yetkilendirme isteğinde bulunun ve yetkilendirme sunucusu yanıtını işleyin.
  • Depolanan kimlik bilgilerini temizleyin.
  • Uygulamanın izinlerini iptal edin.
  • API çağrısını test etme.

Yetkilendirmeyi başlatma

Gerekirse açılış sayfanızı, yetkilendirme akışını başlatacak şekilde değiştirin. Eklenti iki durumda olabilir: Mevcut oturumda kayıtlı jetonlar vardır veya OAuth 2.0 sunucusundan jeton almanız gerekir. Oturumda jeton varsa bir test API çağrısı yapın veya kullanıcıdan oturum açmasını isteyin.

Python

routes.py dosyanızı açın. Öncelikle birkaç sabit değer ve çerez yapılandırmamızı iframe güvenlik önerilerine göre ayarlayın.

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

Eklenti açılış rotanıza gidin (örnek dosyada /classroom-addon). Oturum "credentials" anahtarını içermiyorsa oturum açma sayfası oluşturacak mantık ekleyin.

@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

Bu adım adım açıklamalı kılavuzun kodunu step_02_sign_in modülünde bulabilirsiniz.

application.properties dosyasını açın ve iframe güvenlik önerilerine uygun oturum yapılandırması ekleyin.

# 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

Denetleyici dosyasındaki uç noktaların arkasındaki mantığı işlemek için bir hizmet sınıfı (step_02_sign_in modülünde AuthService.java) oluşturun ve yönlendirme URI'sini, istemci gizli anahtarı dosyasının konumunu ve eklentinizin gerektirdiği kapsamları ayarlayın. Yönlendirme URI'si, kullanıcılarınız uygulamanızı yetkilendirdikten sonra onları belirli bir URI'ye yönlendirmek için kullanılır. client_secret.json dosyanızı nereye yerleştireceğiniz hakkında bilgi edinmek için kaynak koddaki README.md projesinin Proje Kurulumu bölümüne bakın.

@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));
    }
}

Denetleyici dosyasını (step_02_sign_in modülünde AuthController.java) açın ve oturumda credentials anahtarını içermiyorsa oturum açma sayfasını oluşturmak için açılış rotasına mantık ekleyin.

@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);
    }
}

Yetkilendirme sayfanızda, kullanıcının "giriş yapması" için bir bağlantı veya düğme bulunmalıdır. Bu düğmeyi tıklayan kullanıcılar authorize rotasına yönlendirilir.

Yetkilendirme isteyin

Yetkilendirme istemek için kullanıcıyı oluşturun ve bir kimlik doğrulama URL'sine yönlendirin. Bu URL; istenen kapsamlar, sonra yetkilendirme için hedef rota ve web uygulamasının istemci kimliği gibi çeşitli bilgiler içerir. Bunları bu örnek yetkilendirme URL'sinde görebilirsiniz.

Python

routes.py dosyanıza aşağıdaki içe aktarma işlemini ekleyin.

import google_auth_oauthlib.flow

Yeni bir rota oluşturun /authorize. google_auth_oauthlib.flow.Flow örneği oluşturun. Bunu yapmak için dahil edilen from_client_secrets_file yöntemini kullanmanızı önemle tavsiye ederiz.

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

flow'nin redirect_uri değerini ayarlayın. Bu, kullanıcıların uygulamanızı yetkilendirdikten sonra geri dönmesini istediğiniz yoldur. Aşağıdaki örnekte bu değer /callback'dir.

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

authorization_url ve state öğelerini oluşturmak için akış nesnesini kullanın. state değerini oturumda saklayın. Bu değer, daha sonra sunucu yanıtının özgünlüğünü doğrulamak için kullanılır. Son olarak kullanıcıyı authorization_url adresine yönlendirin.

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

Akış nesnesini örneklemek için AuthService.java dosyasına aşağıdaki yöntemleri ekleyin ve ardından yetkilendirme URL'sini almak için kullanın:

  • getClientSecrets() yöntemi, istemci gizli anahtarı dosyasını okur ve bir GoogleClientSecrets nesnesi oluşturur.
  • getFlow() yöntemi, GoogleAuthorizationCodeFlow örneği oluşturur.
  • authorize() yöntemi, yetkilendirme URL'sini almak için GoogleAuthorizationCodeFlow nesnesini, state parametresini ve yönlendirme URI'sini kullanır. state parametresi, yetkilendirme sunucusundan gelen yanıtın özgünlüğünü doğrulamak için kullanılır. Ardından yöntem, yetkilendirme URL'sini vestate parametresini içeren bir harita döndürür.
/** 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;
    }
}

Denetleyici sınıfında hizmet sınıfının bir örneğini oluşturmak için kurucu enjeksiyonu kullanın.

/** 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;
}

/authorize uç noktasını denetleyici sınıfına ekleyin. Bu uç nokta, state parametresini ve yetkilendirme URL'sini almak için AuthService authorize() yöntemini çağırır. Ardından uç nokta, state parametresini oturumda depolar ve kullanıcıları yetkilendirme URL'sine yönlendirir.

/** 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;
    }
}

Sunucu yanıtını işleme

Kullanıcı, yetkilendirmeden sonra önceki adımdaki redirect_uri rotasına geri döner. Önceki örnekte bu rota /callback'tir.

Kullanıcı yetkilendirme sayfasından döndüğünde yanıtta bir code alırsınız. Ardından, kodu erişim ve yenileme jetonlarıyla değiştirin:

Python

Aşağıdaki içe aktarma işlemlerini Flask sunucu dosyanıza ekleyin.

import google.oauth2.credentials
import googleapiclient.discovery

Yolu sunucunuza ekleyin. google_auth_oauthlib.flow.Flow sınıfının başka bir örneğini oluşturun ancak bu sefer önceki adımda kaydedilen durumu yeniden kullanın.

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

Ardından, erişim izni isteyin ve jetonları yenileyin. Neyse ki flow nesnesi bunu gerçekleştirmek için fetch_token yöntemini de içerir. Yöntem, code veya authorization_response bağımsız değişkenlerinin olmasını bekler. İstekteki tam URL olduğu için authorization_response öğesini kullanın.

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

Artık kimlik bilgileriniz eksiksiz. Diğer yöntemler veya rotalarda alınabilmeleri için bunları oturumda saklayın, ardından bir eklenti açılış sayfasına yönlendirin.

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

Hizmet sınıfınıza, yetkilendirme URL'si tarafından gerçekleştirilen yönlendirmeden alınan yetkilendirme kodunu ileterek Credentials nesnesini döndüren bir yöntem ekleyin. Bu Credentials nesnesi daha sonra erişim jetonunu ve yenileme jetonunu almak için kullanılır.

/** 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;
    }
}

Yönlendirme URI'niz için kumandaya bir uç nokta ekleyin. İstekten yetkilendirme kodunu ve state parametresini alın. Bu state parametresini oturumda depolanan state özelliğiyle karşılaştırın. Bunlar eşleşiyorsa yetkilendirme akışına devam edin. Eşleşmezlerse hata döndürülür.

Ardından, AuthService getAndSaveCredentials yöntemini çağırın ve yetkilendirme kodunu parametre olarak iletin. Credentials nesnesini aldıktan sonra oturumda depolayın. Ardından iletişim kutusunu kapatın ve kullanıcıyı eklenti açılış sayfasına yönlendirin.

/** 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 çağrısı test etme

Akış tamamlandığında artık Google API'lerine çağrı gönderebilirsiniz.

Örneğin, kullanıcının profil bilgilerini isteyin. OAuth 2.0 API'sinden kullanıcı bilgilerini isteyebilirsiniz.

Python

OAuth 2.0 discovery API'si ile ilgili dokümanları okuyun. Doldurulan UserInfo nesnesini almak için bu API'yi kullanın.

# 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

Parametre olarak Credentials kullanıp UserInfo nesnesi oluşturan bir hizmet sınıfında yöntem oluşturun.

/** 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;
    }
}

Kullanıcının e-posta adresini gösteren denetleyiciye /test uç noktasını ekleyin.

/** 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);
    }
}

Kimlik bilgilerini temizle

Kullanıcının kimlik bilgilerini mevcut oturumdan kaldırarak "temizleyebilirsiniz". Bu sayede, eklenti açılış sayfasında yönlendirmeyi test edebilirsiniz.

Kullanıcıyı eklenti açılış sayfasına yönlendirmeden önce oturumunu kapattığını belirten bir gösterge göstermenizi öneririz. Uygulamanız, yeni kimlik bilgileri almak için yetkilendirme akışından geçmelidir. Ancak kullanıcılardan uygulamanızı yeniden yetkilendirmeleri istenmez.

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

Alternatif olarak flask.session.clear() değerini kullanabilirsiniz ancak oturumda depolanmış başka değerleriniz varsa bu, istenmeyen etkilere neden olabilir.

Java

Denetleyiciye bir /clear uç noktası ekleyin.

/** 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);
    }
}

Uygulamanın iznini iptal edin

Bir kullanıcı, https://oauth2.googleapis.com/revoke adresine POST isteği göndererek uygulamanızın iznini iptal edebilir. İstek, kullanıcının erişim jetonunu içermelidir.

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

Hizmet sınıfına, iptal uç noktasını çağıran bir yöntem ekleyin.

/** 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;
    }
}

Denetleyiciye, oturumu temizleyen ve iptal başarılıysa kullanıcıyı yetkilendirme sayfasına yönlendiren bir uç nokta (/revoke) ekleyin.

/** 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);
    }
}

Eklentiyi test etme

Öğretmen test kullanıcılarınızdan biri olarak Google Classroom'da oturum açın. Sınıf çalışmaları sekmesine gidin ve yeni bir Ödev oluşturun. Metin alanının altındaki Eklentiler düğmesini tıklayın ve ardından eklentinizi seçin. İçeriden yerleştirilmiş çerçeve açılır ve eklenti, GWM SDK'sının Uygulama Yapılandırması sayfasında belirttiğiniz Ekleme Kurulumu URI'sini yükler.

Tebrikler! Bir sonraki adıma (eklentinize yapılan tekrar ziyaretleri işleme) geçmeye hazırsınız.