ব্যবহারকারী সাইন ইন করুন

ক্লাসরুম অ্যাড-অন ওয়াকথ্রু সিরিজে এটি দ্বিতীয় ওয়াকথ্রু।

এই ওয়াকথ্রুতে, আপনি ওয়েব অ্যাপ্লিকেশনে Google সাইন-ইন যোগ করেন। ক্লাসরুম অ্যাড-অনগুলির জন্য এটি একটি প্রয়োজনীয় আচরণ। API-এ সমস্ত ভবিষ্যতের কলের জন্য এই অনুমোদন প্রবাহ থেকে শংসাপত্রগুলি ব্যবহার করুন৷

এই ওয়াকথ্রু চলাকালীন, আপনি নিম্নলিখিতগুলি সম্পূর্ণ করবেন:

  • একটি আইফ্রেমের মধ্যে সেশন ডেটা বজায় রাখতে আপনার ওয়েব অ্যাপ কনফিগার করুন।
  • Google OAuth 2.0 সার্ভার-টু-সার্ভার সাইন ইন ফ্লো বাস্তবায়ন করুন।
  • OAuth 2.0 API এ একটি কল ইস্যু করুন।
  • অনুমোদন, সাইন আউট এবং API কল পরীক্ষা করার জন্য অতিরিক্ত রুট তৈরি করুন।

একবার শেষ হয়ে গেলে, আপনি আপনার ওয়েব অ্যাপে ব্যবহারকারীদের সম্পূর্ণরূপে অনুমোদন করতে পারেন এবং Google API-এ কল ইস্যু করতে পারেন।

অনুমোদন প্রবাহ বুঝতে

Google APIগুলি প্রমাণীকরণ এবং অনুমোদনের জন্য OAuth 2.0 প্রোটোকল ব্যবহার করে৷ Google এর OAuth বাস্তবায়নের সম্পূর্ণ বিবরণ Google Identity OAuth গাইডে পাওয়া যায়।

আপনার অ্যাপ্লিকেশনের শংসাপত্রগুলি Google ক্লাউডে পরিচালিত হয়৷ একবার এগুলি তৈরি হয়ে গেলে, ব্যবহারকারীকে প্রমাণীকরণ এবং অনুমোদন করার জন্য একটি চার-পদক্ষেপ প্রক্রিয়া প্রয়োগ করুন:

  1. অনুমোদনের জন্য অনুরোধ করুন। এই অনুরোধের অংশ হিসাবে একটি কলব্যাক URL প্রদান করুন৷ সম্পূর্ণ হলে, আপনি একটি অনুমোদন URL পাবেন।
  2. ব্যবহারকারীকে অনুমোদন URL-এ পুনর্নির্দেশ করুন। ফলস্বরূপ পৃষ্ঠাটি ব্যবহারকারীকে আপনার অ্যাপের প্রয়োজনীয় অনুমতিগুলির বিষয়ে অবহিত করে এবং তাদের অ্যাক্সেসের অনুমতি দেওয়ার জন্য অনুরোধ করে। সম্পূর্ণ হলে, ব্যবহারকারীকে কলব্যাক ইউআরএলে পাঠানো হয়।
  3. আপনার কলব্যাক রুটে একটি অনুমোদন কোড পান। একটি অ্যাক্সেস টোকেন এবং একটি রিফ্রেশ টোকেনের জন্য অনুমোদন কোড বিনিময় করুন৷
  4. টোকেন ব্যবহার করে একটি Google API এ কল করুন।

OAuth 2.0 শংসাপত্রগুলি পান৷

ওভারভিউ পৃষ্ঠায় বর্ণিত হিসাবে আপনি OAuth শংসাপত্র তৈরি এবং ডাউনলোড করেছেন তা নিশ্চিত করুন৷ ব্যবহারকারী সাইন ইন করতে আপনার প্রকল্প এই শংসাপত্র ব্যবহার করা আবশ্যক.

অনুমোদন প্রবাহ বাস্তবায়ন

এই বৈশিষ্ট্যগুলি সহ বর্ণিত প্রবাহ উপলব্ধি করতে আমাদের ওয়েব অ্যাপে যুক্তি এবং রুট যোগ করুন:

  • ল্যান্ডিং পৃষ্ঠায় পৌঁছানোর পরে অনুমোদনের প্রবাহ শুরু করুন।
  • অনুমোদনের অনুরোধ করুন এবং অনুমোদন সার্ভার প্রতিক্রিয়া পরিচালনা করুন।
  • সংরক্ষিত শংসাপত্রগুলি সাফ করুন।
  • অ্যাপের অনুমতি প্রত্যাহার করুন।
  • একটি API কল পরীক্ষা করুন।

অনুমোদন শুরু করুন

প্রয়োজনে অনুমোদনের প্রবাহ শুরু করতে আপনার ল্যান্ডিং পৃষ্ঠা পরিবর্তন করুন। অ্যাড-অন দুটি সম্ভাব্য অবস্থায় হতে পারে; হয় বর্তমান সেশনে সংরক্ষিত টোকেন আছে, অথবা আপনাকে OAuth 2.0 সার্ভার থেকে টোকেন পেতে হবে। সেশনে টোকেন থাকলে একটি পরীক্ষা API কল করুন, অথবা অন্যথায় ব্যবহারকারীকে সাইন ইন করতে অনুরোধ করুন।

পাইথন

আপনার routes.py ফাইল খুলুন। প্রথমে কয়েকটি ধ্রুবক এবং আমাদের কুকি কনফিগারেশন আইফ্রেম নিরাপত্তা সুপারিশ অনুযায়ী সেট করুন।

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

আপনার অ্যাড-অন ল্যান্ডিং রুটে যান (এটি উদাহরণ ফাইলে /classroom-addon )। সেশনে "প্রমাণপত্র" কী না থাকলে একটি সাইন-ইন পৃষ্ঠা রেন্ডার করতে যুক্তি যোগ করুন৷

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

জাভা

এই ওয়াকথ্রুটির কোডটি step_02_sign_in মডিউলে পাওয়া যাবে।

application.properties ফাইলটি খুলুন এবং সেশন কনফিগারেশন যোগ করুন যা iframe নিরাপত্তা সুপারিশ অনুসরণ করে।

# 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

কন্ট্রোলার ফাইলের এন্ডপয়েন্টগুলির পিছনে যুক্তি পরিচালনা করতে এবং আপনার অ্যাড-অনের জন্য প্রয়োজনীয় স্কোপগুলি রিডাইরেক্ট ইউআরআই, ক্লায়েন্ট সিক্রেটস ফাইলের অবস্থান এবং স্কোপ সেট আপ করতে একটি পরিষেবা ক্লাস ( step_02_sign_in মডিউলে AuthService.java ) তৈরি করুন৷ রিডাইরেক্ট ইউআরআই ব্যবহার করা হয় আপনার ব্যবহারকারীরা আপনার অ্যাপকে অনুমোদন করার পরে একটি নির্দিষ্ট ইউআরআই-এ পুনরায় রুট করতে। আপনার client_secret.json ফাইলটি কোথায় রাখবেন সে সম্পর্কে তথ্যের জন্য সোর্স কোডে README.md এর প্রজেক্ট সেট আপ বিভাগটি দেখুন।

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

কন্ট্রোলার ফাইলটি খুলুন ( step_02_sign_in মডিউলে AuthController.java ) এবং সেশনে credentials কী না থাকলে সাইন-ইন পৃষ্ঠা রেন্ডার করতে ল্যান্ডিং রুটে যুক্তি যোগ করুন।

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

আপনার অনুমোদন পৃষ্ঠায় ব্যবহারকারীর "সাইন ইন" করার জন্য একটি লিঙ্ক বা বোতাম থাকা উচিত। এটিতে ক্লিক করলে ব্যবহারকারীকে authorize রুটে পুনঃনির্দেশিত করা উচিত।

অনুমোদনের জন্য অনুরোধ করুন

অনুমোদনের অনুরোধ করতে, ব্যবহারকারীকে একটি প্রমাণীকরণ URL-এ নির্মাণ এবং পুনঃনির্দেশ করুন। এই ইউআরএলে তথ্যের কিছু অংশ রয়েছে, যেমন অনুরোধ করা স্কোপ, অনুমোদনের পরে গন্তব্যের রুট এবং ওয়েব অ্যাপের ক্লায়েন্ট আইডি। আপনি এই নমুনা অনুমোদন URL এ দেখতে পারেন.

পাইথন

আপনার routes.py ফাইলে নিম্নলিখিত আমদানি যোগ করুন।

import google_auth_oauthlib.flow

একটি নতুন রুট তৈরি করুন /authorizegoogle_auth_oauthlib.flow.Flow এর একটি উদাহরণ তৈরি করুন; আমরা দৃঢ়ভাবে এটি করার জন্য অন্তর্ভুক্ত from_client_secrets_file পদ্ধতি ব্যবহার করার পরামর্শ দিই।

@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 redirect_uri সেট করুন; এটি সেই রুট যেখানে আপনি ব্যবহারকারীদের আপনার অ্যাপ অনুমোদন করার পরে ফিরে যেতে চান৷ নিম্নলিখিত উদাহরণে এটি /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)

authorization_url এবং state গঠন করতে ফ্লো অবজেক্ট ব্যবহার করুন। অধিবেশনে state সংরক্ষণ করুন; এটি পরে সার্ভার প্রতিক্রিয়ার সত্যতা যাচাই করতে ব্যবহৃত হয়। অবশেষে, ব্যবহারকারীকে 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")

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

জাভা

ফ্লো অবজেক্টকে ইনস্ট্যান্টিয়েট করতে AuthService.java ফাইলে নিম্নলিখিত পদ্ধতিগুলি যোগ করুন এবং তারপর অনুমোদন URL পুনরুদ্ধার করতে এটি ব্যবহার করুন:

  • getClientSecrets() পদ্ধতি ক্লায়েন্ট গোপন ফাইলটি পড়ে এবং একটি GoogleClientSecrets অবজেক্ট তৈরি করে।
  • getFlow() পদ্ধতি GoogleAuthorizationCodeFlow এর একটি উদাহরণ তৈরি করে।
  • authorize() পদ্ধতি GoogleAuthorizationCodeFlow অবজেক্ট, state প্যারামিটার এবং ইউআরআই রিডাইরেক্ট ব্যবহার করে অনুমোদনের URL পুনরুদ্ধার করতে। state প্যারামিটারটি অনুমোদন সার্ভার থেকে প্রতিক্রিয়ার সত্যতা যাচাই করতে ব্যবহৃত হয়। পদ্ধতিটি তারপর অনুমোদন URL এবং state পরামিতি সহ একটি মানচিত্র প্রদান করে।
/** 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;
    }
}

কন্ট্রোলার ক্লাসে সার্ভিস ক্লাসের একটি উদাহরণ তৈরি করতে কনস্ট্রাক্টর ইনজেকশন ব্যবহার করুন।

/** 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 এন্ডপয়েন্ট যোগ করুন। state প্যারামিটার এবং অনুমোদন URL পুনরুদ্ধার করতে এই এন্ডপয়েন্টটি AuthService authorize() পদ্ধতিকে কল করে। তারপর, এন্ডপয়েন্ট সেশনে state প্যারামিটার সঞ্চয় করে এবং ব্যবহারকারীদের অনুমোদন URL-এ পুনঃনির্দেশ করে।

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

সার্ভার প্রতিক্রিয়া হ্যান্ডেল

অনুমোদন করার পর, ব্যবহারকারী পূর্ববর্তী ধাপ থেকে redirect_uri রুটে ফিরে আসে। পূর্ববর্তী উদাহরণে, এই রুটটি হল /callback

যখন ব্যবহারকারী অনুমোদন পৃষ্ঠা থেকে ফিরে আসে তখন আপনি প্রতিক্রিয়াতে একটি code পাবেন। তারপর অ্যাক্সেসের জন্য কোড বিনিময় করুন এবং টোকেন রিফ্রেশ করুন:

পাইথন

আপনার ফ্লাস্ক সার্ভার ফাইলে নিম্নলিখিত আমদানি যোগ করুন।

import google.oauth2.credentials
import googleapiclient.discovery

আপনার সার্ভারে রুট যোগ করুন. google_auth_oauthlib.flow.Flow এর আরেকটি দৃষ্টান্ত তৈরি করুন, কিন্তু এইবার পূর্ববর্তী ধাপে সংরক্ষিত স্থিতি পুনরায় ব্যবহার করুন।

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

এরপরে, অ্যাক্সেসের অনুরোধ করুন এবং টোকেন রিফ্রেশ করুন। সৌভাগ্যবশত, flow অবজেক্টে এটি সম্পন্ন করার জন্য fetch_token পদ্ধতিও রয়েছে। পদ্ধতিটি code বা authorization_response আর্গুমেন্ট আশা করে। authorization_response ব্যবহার করুন, কারণ এটি অনুরোধের সম্পূর্ণ URL।

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

আপনি এখন সম্পূর্ণ শংসাপত্র আছে! সেশনে সেগুলি সংরক্ষণ করুন যাতে সেগুলি অন্য পদ্ধতি বা রুটে পুনরুদ্ধার করা যায়, তারপর একটি অ্যাড-অন ল্যান্ডিং পৃষ্ঠায় পুনঃনির্দেশিত করুন৷

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

জাভা

আপনার পরিষেবা শ্রেণীতে একটি পদ্ধতি যোগ করুন যা অনুমোদনের URL দ্বারা সম্পাদিত পুনঃনির্দেশ থেকে পুনরুদ্ধারকৃত অনুমোদন কোডটি পাস করে Credentials বস্তু প্রদান করে। এই Credentials বস্তুটি পরে ব্যবহার করা হয় অ্যাক্সেস টোকেন পুনরুদ্ধার করতে এবং টোকেন রিফ্রেশ করতে।

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

কন্ট্রোলারে আপনার রিডাইরেক্ট URI-এর জন্য একটি শেষ পয়েন্ট যোগ করুন। অনুরোধ থেকে অনুমোদন কোড এবং state পরামিতি পুনরুদ্ধার করুন. এই state প্যারামিটারটিকে সেশনে সঞ্চিত state অ্যাট্রিবিউটের সাথে তুলনা করুন। যদি তারা মিলে যায়, তাহলে অনুমোদনের প্রবাহ চালিয়ে যান। যদি তারা মেলে না, একটি ত্রুটি ফেরত.

তারপরে, AuthService getAndSaveCredentials পদ্ধতিতে কল করুন এবং একটি প্যারামিটার হিসাবে অনুমোদন কোডটি পাস করুন৷ Credentials অবজেক্ট পুনরুদ্ধার করার পরে, এটি সেশনে সংরক্ষণ করুন। তারপর, ডায়ালগটি বন্ধ করুন এবং ব্যবহারকারীকে অ্যাড-অন ল্যান্ডিং পৃষ্ঠায় পুনঃনির্দেশ করুন৷

/** 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 কল পরীক্ষা করুন

প্রবাহ সম্পূর্ণ হলে, আপনি এখন Google API-এ কল ইস্যু করতে পারেন!

একটি উদাহরণ হিসাবে, ব্যবহারকারীর প্রোফাইল তথ্য অনুরোধ. আপনি OAuth 2.0 API থেকে ব্যবহারকারীর তথ্যের জন্য অনুরোধ করতে পারেন।

পাইথন

OAuth 2.0 আবিষ্কার API এর জন্য ডকুমেন্টেশন পড়ুন একটি জনবহুল UserInfo অবজেক্ট পেতে এটি ব্যবহার করুন।

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

জাভা

পরিষেবা শ্রেণিতে একটি পদ্ধতি তৈরি করুন যা একটি পরামিতি হিসাবে Credentials ব্যবহার করে একটি UserInfo অবজেক্ট তৈরি করে।

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

ব্যবহারকারীর ইমেল প্রদর্শন করে এমন নিয়ামকটিতে /test এন্ডপয়েন্ট যোগ করুন।

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

সাফ প্রমাণপত্রাদি

আপনি বর্তমান অধিবেশন থেকে ব্যবহারকারীর শংসাপত্রগুলিকে সরিয়ে দিয়ে "সাফ" করতে পারেন৷ এটি আপনাকে অ্যাড-অন ল্যান্ডিং পৃষ্ঠায় রাউটিং পরীক্ষা করতে দেয়।

আমরা অ্যাড-অন ল্যান্ডিং পৃষ্ঠায় রিডাইরেক্ট করার আগে ব্যবহারকারী সাইন আউট করেছেন এমন একটি ইঙ্গিত দেখানোর পরামর্শ দিই। নতুন শংসাপত্রগুলি পেতে আপনার অ্যাপটিকে অনুমোদনের প্রবাহের মধ্য দিয়ে যেতে হবে, তবে ব্যবহারকারীদের আপনার অ্যাপকে পুনরায় অনুমোদন করার জন্য অনুরোধ করা হবে না।

পাইথন

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

বিকল্পভাবে, flask.session.clear() ব্যবহার করুন, তবে আপনার যদি সেশনে অন্যান্য মান সংরক্ষিত থাকে তবে এটির অনিচ্ছাকৃত প্রভাব থাকতে পারে।

জাভা

কন্ট্রোলারে, একটি /clear এন্ডপয়েন্ট যোগ করুন।

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

অ্যাপের অনুমতি প্রত্যাহার করুন

একজন ব্যবহারকারী https://oauth2.googleapis.com/revoke এ একটি POST অনুরোধ পাঠিয়ে আপনার অ্যাপের অনুমতি প্রত্যাহার করতে পারেন। অনুরোধে ব্যবহারকারীর অ্যাক্সেস টোকেন থাকা উচিত।

পাইথন

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

জাভা

পরিষেবা ক্লাসে একটি পদ্ধতি যোগ করুন যা প্রত্যাহার শেষ পয়েন্টে একটি কল করে।

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

কন্ট্রোলারে একটি এন্ডপয়েন্ট যোগ করুন, /revoke , যা সেশনটি সাফ করে এবং ব্যবহারকারীকে অনুমোদন পৃষ্ঠায় পুনঃনির্দেশ করে যদি প্রত্যাহার সফল হয়।

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

অ্যাড-অন পরীক্ষা করুন

আপনার শিক্ষক পরীক্ষার ব্যবহারকারীদের একজন হিসাবে Google ক্লাসরুমে সাইন ইন করুন৷ ক্লাসওয়ার্ক ট্যাবে নেভিগেট করুন এবং একটি নতুন অ্যাসাইনমেন্ট তৈরি করুন। পাঠ্য এলাকার নীচে অ্যাড-অন বোতামে ক্লিক করুন, তারপর আপনার অ্যাড-অন নির্বাচন করুন। iframe খোলে এবং অ্যাড-অন সংযুক্তি সেটআপ URI লোড করে যা আপনি GWM SDK-এর অ্যাপ কনফিগারেশন পৃষ্ঠায় উল্লেখ করেছেন।

অভিনন্দন! আপনি পরবর্তী ধাপে এগিয়ে যাওয়ার জন্য প্রস্তুত: আপনার অ্যাড-অনে বারবার ভিজিট পরিচালনা করা

,

ক্লাসরুম অ্যাড-অন ওয়াকথ্রু সিরিজে এটি দ্বিতীয় ওয়াকথ্রু।

এই ওয়াকথ্রুতে, আপনি ওয়েব অ্যাপ্লিকেশনে Google সাইন-ইন যোগ করেন। ক্লাসরুম অ্যাড-অনগুলির জন্য এটি একটি প্রয়োজনীয় আচরণ। API-এ সমস্ত ভবিষ্যতের কলের জন্য এই অনুমোদন প্রবাহ থেকে শংসাপত্রগুলি ব্যবহার করুন৷

এই ওয়াকথ্রু চলাকালীন, আপনি নিম্নলিখিতগুলি সম্পূর্ণ করবেন:

  • একটি আইফ্রেমের মধ্যে সেশন ডেটা বজায় রাখতে আপনার ওয়েব অ্যাপ কনফিগার করুন।
  • Google OAuth 2.0 সার্ভার-টু-সার্ভার সাইন ইন ফ্লো বাস্তবায়ন করুন।
  • OAuth 2.0 API এ একটি কল ইস্যু করুন।
  • অনুমোদন, সাইন আউট এবং API কল পরীক্ষা করার জন্য অতিরিক্ত রুট তৈরি করুন।

একবার শেষ হয়ে গেলে, আপনি আপনার ওয়েব অ্যাপে ব্যবহারকারীদের সম্পূর্ণরূপে অনুমোদন করতে পারেন এবং Google API-এ কল ইস্যু করতে পারেন।

অনুমোদন প্রবাহ বুঝতে

Google APIগুলি প্রমাণীকরণ এবং অনুমোদনের জন্য OAuth 2.0 প্রোটোকল ব্যবহার করে৷ Google এর OAuth বাস্তবায়নের সম্পূর্ণ বিবরণ Google Identity OAuth গাইডে পাওয়া যায়।

আপনার অ্যাপ্লিকেশনের শংসাপত্রগুলি Google ক্লাউডে পরিচালিত হয়৷ একবার এগুলি তৈরি হয়ে গেলে, ব্যবহারকারীকে প্রমাণীকরণ এবং অনুমোদন করার জন্য একটি চার-পদক্ষেপ প্রক্রিয়া প্রয়োগ করুন:

  1. অনুমোদনের জন্য অনুরোধ করুন। এই অনুরোধের অংশ হিসাবে একটি কলব্যাক URL প্রদান করুন৷ সম্পূর্ণ হলে, আপনি একটি অনুমোদন URL পাবেন।
  2. ব্যবহারকারীকে অনুমোদন URL-এ পুনর্নির্দেশ করুন। ফলস্বরূপ পৃষ্ঠাটি ব্যবহারকারীকে আপনার অ্যাপের প্রয়োজনীয় অনুমতিগুলির বিষয়ে অবহিত করে এবং তাদের অ্যাক্সেসের অনুমতি দেওয়ার জন্য অনুরোধ করে। সম্পূর্ণ হলে, ব্যবহারকারীকে কলব্যাক ইউআরএলে পাঠানো হয়।
  3. আপনার কলব্যাক রুটে একটি অনুমোদন কোড পান। একটি অ্যাক্সেস টোকেন এবং একটি রিফ্রেশ টোকেনের জন্য অনুমোদন কোড বিনিময় করুন৷
  4. টোকেন ব্যবহার করে একটি Google API এ কল করুন।

OAuth 2.0 শংসাপত্রগুলি পান৷

ওভারভিউ পৃষ্ঠায় বর্ণিত হিসাবে আপনি OAuth শংসাপত্র তৈরি এবং ডাউনলোড করেছেন তা নিশ্চিত করুন৷ ব্যবহারকারী সাইন ইন করতে আপনার প্রকল্প এই শংসাপত্র ব্যবহার করা আবশ্যক.

অনুমোদন প্রবাহ বাস্তবায়ন

এই বৈশিষ্ট্যগুলি সহ বর্ণিত প্রবাহ উপলব্ধি করতে আমাদের ওয়েব অ্যাপে যুক্তি এবং রুট যোগ করুন:

  • ল্যান্ডিং পৃষ্ঠায় পৌঁছানোর পরে অনুমোদনের প্রবাহ শুরু করুন।
  • অনুমোদনের অনুরোধ করুন এবং অনুমোদন সার্ভার প্রতিক্রিয়া পরিচালনা করুন।
  • সংরক্ষিত শংসাপত্রগুলি সাফ করুন।
  • অ্যাপের অনুমতি প্রত্যাহার করুন।
  • একটি API কল পরীক্ষা করুন।

অনুমোদন শুরু করুন

প্রয়োজনে অনুমোদনের প্রবাহ শুরু করতে আপনার ল্যান্ডিং পৃষ্ঠা পরিবর্তন করুন। অ্যাড-অন দুটি সম্ভাব্য অবস্থায় হতে পারে; হয় বর্তমান সেশনে সংরক্ষিত টোকেন আছে, অথবা আপনাকে OAuth 2.0 সার্ভার থেকে টোকেন পেতে হবে। সেশনে টোকেন থাকলে একটি পরীক্ষা API কল করুন, অথবা অন্যথায় ব্যবহারকারীকে সাইন ইন করতে অনুরোধ করুন।

পাইথন

আপনার routes.py ফাইল খুলুন। প্রথমে কয়েকটি ধ্রুবক এবং আমাদের কুকি কনফিগারেশন আইফ্রেম নিরাপত্তা সুপারিশ অনুযায়ী সেট করুন।

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

আপনার অ্যাড-অন ল্যান্ডিং রুটে যান (এটি উদাহরণ ফাইলে /classroom-addon )। সেশনে "প্রমাণপত্র" কী না থাকলে একটি সাইন-ইন পৃষ্ঠা রেন্ডার করতে যুক্তি যোগ করুন৷

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

জাভা

এই ওয়াকথ্রুটির কোডটি step_02_sign_in মডিউলে পাওয়া যাবে।

application.properties ফাইলটি খুলুন এবং সেশন কনফিগারেশন যোগ করুন যা iframe নিরাপত্তা সুপারিশ অনুসরণ করে।

# 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

কন্ট্রোলার ফাইলের এন্ডপয়েন্টগুলির পিছনে যুক্তি পরিচালনা করতে এবং আপনার অ্যাড-অনের জন্য প্রয়োজনীয় স্কোপগুলি রিডাইরেক্ট ইউআরআই, ক্লায়েন্ট সিক্রেটস ফাইলের অবস্থান এবং স্কোপ সেট আপ করতে একটি পরিষেবা ক্লাস ( step_02_sign_in মডিউলে AuthService.java ) তৈরি করুন৷ রিডাইরেক্ট ইউআরআই ব্যবহার করা হয় আপনার ব্যবহারকারীরা আপনার অ্যাপকে অনুমোদন করার পরে একটি নির্দিষ্ট ইউআরআই-এ পুনরায় রুট করতে। আপনার client_secret.json ফাইলটি কোথায় রাখবেন সে সম্পর্কে তথ্যের জন্য সোর্স কোডে README.md এর প্রজেক্ট সেট আপ বিভাগটি দেখুন।

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

কন্ট্রোলার ফাইলটি খুলুন ( step_02_sign_in মডিউলে AuthController.java ) এবং সেশনে credentials কী না থাকলে সাইন-ইন পৃষ্ঠা রেন্ডার করতে ল্যান্ডিং রুটে যুক্তি যোগ করুন।

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

আপনার অনুমোদন পৃষ্ঠায় ব্যবহারকারীর "সাইন ইন" করার জন্য একটি লিঙ্ক বা বোতাম থাকা উচিত। এটিতে ক্লিক করলে ব্যবহারকারীকে authorize রুটে পুনঃনির্দেশিত করা উচিত।

অনুমোদনের জন্য অনুরোধ করুন

অনুমোদনের অনুরোধ করতে, ব্যবহারকারীকে একটি প্রমাণীকরণ URL-এ নির্মাণ এবং পুনঃনির্দেশ করুন। এই ইউআরএলে তথ্যের কিছু অংশ রয়েছে, যেমন অনুরোধ করা স্কোপ, অনুমোদনের পরে গন্তব্যের রুট এবং ওয়েব অ্যাপের ক্লায়েন্ট আইডি। আপনি এই নমুনা অনুমোদন URL এ দেখতে পারেন.

পাইথন

আপনার routes.py ফাইলে নিম্নলিখিত আমদানি যোগ করুন।

import google_auth_oauthlib.flow

একটি নতুন রুট তৈরি করুন /authorizegoogle_auth_oauthlib.flow.Flow এর একটি উদাহরণ তৈরি করুন; আমরা দৃঢ়ভাবে এটি করার জন্য অন্তর্ভুক্ত from_client_secrets_file পদ্ধতি ব্যবহার করার পরামর্শ দিই।

@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 redirect_uri সেট করুন; এটি সেই রুট যেখানে আপনি ব্যবহারকারীদের আপনার অ্যাপ অনুমোদন করার পরে ফিরে যেতে চান৷ নিম্নলিখিত উদাহরণে এটি /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)

authorization_url এবং state গঠন করতে ফ্লো অবজেক্ট ব্যবহার করুন। অধিবেশনে state সংরক্ষণ করুন; এটি পরে সার্ভার প্রতিক্রিয়ার সত্যতা যাচাই করতে ব্যবহৃত হয়। অবশেষে, ব্যবহারকারীকে 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")

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

জাভা

ফ্লো অবজেক্টকে ইনস্ট্যান্টিয়েট করতে AuthService.java ফাইলে নিম্নলিখিত পদ্ধতিগুলি যোগ করুন এবং তারপর অনুমোদন URL পুনরুদ্ধার করতে এটি ব্যবহার করুন:

  • getClientSecrets() পদ্ধতি ক্লায়েন্ট গোপন ফাইলটি পড়ে এবং একটি GoogleClientSecrets অবজেক্ট তৈরি করে।
  • getFlow() পদ্ধতি GoogleAuthorizationCodeFlow এর একটি উদাহরণ তৈরি করে।
  • authorize() পদ্ধতি GoogleAuthorizationCodeFlow অবজেক্ট, state প্যারামিটার এবং ইউআরআই রিডাইরেক্ট ব্যবহার করে অনুমোদনের URL পুনরুদ্ধার করতে। state প্যারামিটারটি অনুমোদন সার্ভার থেকে প্রতিক্রিয়ার সত্যতা যাচাই করতে ব্যবহৃত হয়। পদ্ধতিটি তারপর অনুমোদন URL এবং state পরামিতি সহ একটি মানচিত্র প্রদান করে।
/** 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;
    }
}

কন্ট্রোলার ক্লাসে সার্ভিস ক্লাসের একটি উদাহরণ তৈরি করতে কনস্ট্রাক্টর ইনজেকশন ব্যবহার করুন।

/** 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 এন্ডপয়েন্ট যোগ করুন। state প্যারামিটার এবং অনুমোদন URL পুনরুদ্ধার করতে এই এন্ডপয়েন্টটি AuthService authorize() পদ্ধতিকে কল করে। তারপর, এন্ডপয়েন্ট সেশনে state প্যারামিটার সঞ্চয় করে এবং ব্যবহারকারীদের অনুমোদন URL-এ পুনঃনির্দেশ করে।

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

সার্ভার প্রতিক্রিয়া হ্যান্ডেল

অনুমোদন করার পর, ব্যবহারকারী পূর্ববর্তী ধাপ থেকে redirect_uri রুটে ফিরে আসে। পূর্ববর্তী উদাহরণে, এই রুটটি হল /callback

যখন ব্যবহারকারী অনুমোদন পৃষ্ঠা থেকে ফিরে আসে তখন আপনি প্রতিক্রিয়াতে একটি code পাবেন। তারপর অ্যাক্সেসের জন্য কোড বিনিময় করুন এবং টোকেন রিফ্রেশ করুন:

পাইথন

আপনার ফ্লাস্ক সার্ভার ফাইলে নিম্নলিখিত আমদানি যোগ করুন।

import google.oauth2.credentials
import googleapiclient.discovery

আপনার সার্ভারে রুট যোগ করুন. google_auth_oauthlib.flow.Flow এর আরেকটি দৃষ্টান্ত তৈরি করুন, কিন্তু এইবার পূর্ববর্তী ধাপে সংরক্ষিত স্থিতি পুনরায় ব্যবহার করুন।

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

এরপরে, অ্যাক্সেসের অনুরোধ করুন এবং টোকেন রিফ্রেশ করুন। সৌভাগ্যবশত, flow অবজেক্টে এটি সম্পন্ন করার জন্য fetch_token পদ্ধতিও রয়েছে। পদ্ধতিটি code বা authorization_response আর্গুমেন্ট আশা করে। authorization_response ব্যবহার করুন, কারণ এটি অনুরোধের সম্পূর্ণ URL।

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

আপনি এখন সম্পূর্ণ শংসাপত্র আছে! সেশনে সেগুলি সংরক্ষণ করুন যাতে সেগুলি অন্য পদ্ধতি বা রুটে পুনরুদ্ধার করা যায়, তারপর একটি অ্যাড-অন ল্যান্ডিং পৃষ্ঠায় পুনঃনির্দেশিত করুন৷

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

জাভা

আপনার পরিষেবা শ্রেণীতে একটি পদ্ধতি যোগ করুন যা অনুমোদনের URL দ্বারা সম্পাদিত পুনঃনির্দেশ থেকে পুনরুদ্ধারকৃত অনুমোদন কোডটি পাস করে Credentials বস্তু প্রদান করে। এই Credentials বস্তুটি পরে ব্যবহার করা হয় অ্যাক্সেস টোকেন পুনরুদ্ধার করতে এবং টোকেন রিফ্রেশ করতে।

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

কন্ট্রোলারে আপনার রিডাইরেক্ট URI-এর জন্য একটি শেষ পয়েন্ট যোগ করুন। অনুরোধ থেকে অনুমোদন কোড এবং state পরামিতি পুনরুদ্ধার করুন. এই state প্যারামিটারটিকে সেশনে সঞ্চিত state অ্যাট্রিবিউটের সাথে তুলনা করুন। যদি তারা মিলে যায়, তাহলে অনুমোদনের প্রবাহ চালিয়ে যান। যদি তারা মেলে না, একটি ত্রুটি ফেরত.

তারপরে, AuthService getAndSaveCredentials পদ্ধতিতে কল করুন এবং একটি প্যারামিটার হিসাবে অনুমোদন কোডটি পাস করুন৷ Credentials অবজেক্ট পুনরুদ্ধার করার পরে, এটি সেশনে সংরক্ষণ করুন। তারপর, ডায়ালগটি বন্ধ করুন এবং ব্যবহারকারীকে অ্যাড-অন ল্যান্ডিং পৃষ্ঠায় পুনঃনির্দেশ করুন৷

/** 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 কল পরীক্ষা করুন

প্রবাহ সম্পূর্ণ হলে, আপনি এখন Google API-এ কল ইস্যু করতে পারেন!

একটি উদাহরণ হিসাবে, ব্যবহারকারীর প্রোফাইল তথ্য অনুরোধ. আপনি OAuth 2.0 API থেকে ব্যবহারকারীর তথ্যের জন্য অনুরোধ করতে পারেন।

পাইথন

OAuth 2.0 আবিষ্কার API এর জন্য ডকুমেন্টেশন পড়ুন একটি জনবহুল UserInfo অবজেক্ট পেতে এটি ব্যবহার করুন।

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

জাভা

পরিষেবা শ্রেণিতে একটি পদ্ধতি তৈরি করুন যা একটি পরামিতি হিসাবে Credentials ব্যবহার করে একটি UserInfo অবজেক্ট তৈরি করে।

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

ব্যবহারকারীর ইমেল প্রদর্শন করে এমন নিয়ামকটিতে /test এন্ডপয়েন্ট যোগ করুন।

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

সাফ প্রমাণপত্রাদি

আপনি বর্তমান অধিবেশন থেকে ব্যবহারকারীর শংসাপত্রগুলিকে সরিয়ে দিয়ে "সাফ" করতে পারেন৷ এটি আপনাকে অ্যাড-অন ল্যান্ডিং পৃষ্ঠায় রাউটিং পরীক্ষা করতে দেয়।

আমরা অ্যাড-অন ল্যান্ডিং পৃষ্ঠায় রিডাইরেক্ট করার আগে ব্যবহারকারী সাইন আউট করেছেন এমন একটি ইঙ্গিত দেখানোর পরামর্শ দিই। নতুন শংসাপত্রগুলি পেতে আপনার অ্যাপটিকে অনুমোদনের প্রবাহের মধ্য দিয়ে যেতে হবে, তবে ব্যবহারকারীদের আপনার অ্যাপকে পুনরায় অনুমোদন করার জন্য অনুরোধ করা হবে না।

পাইথন

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

বিকল্পভাবে, flask.session.clear() ব্যবহার করুন, তবে আপনার যদি সেশনে অন্যান্য মান সংরক্ষিত থাকে তবে এটির অনিচ্ছাকৃত প্রভাব থাকতে পারে।

জাভা

কন্ট্রোলারে, একটি /clear এন্ডপয়েন্ট যোগ করুন।

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

অ্যাপের অনুমতি প্রত্যাহার করুন

একজন ব্যবহারকারী https://oauth2.googleapis.com/revoke এ একটি POST অনুরোধ পাঠিয়ে আপনার অ্যাপের অনুমতি প্রত্যাহার করতে পারেন। অনুরোধে ব্যবহারকারীর অ্যাক্সেস টোকেন থাকা উচিত।

পাইথন

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

জাভা

পরিষেবা ক্লাসে একটি পদ্ধতি যোগ করুন যা প্রত্যাহার শেষ পয়েন্টে একটি কল করে।

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

কন্ট্রোলারে একটি এন্ডপয়েন্ট যোগ করুন, /revoke , যা সেশনটি সাফ করে এবং ব্যবহারকারীকে অনুমোদন পৃষ্ঠায় পুনঃনির্দেশ করে যদি প্রত্যাহার সফল হয়।

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

অ্যাড-অন পরীক্ষা করুন

আপনার শিক্ষক পরীক্ষার ব্যবহারকারীদের একজন হিসাবে Google ক্লাসরুমে সাইন ইন করুন৷ ক্লাসওয়ার্ক ট্যাবে নেভিগেট করুন এবং একটি নতুন অ্যাসাইনমেন্ট তৈরি করুন। পাঠ্য এলাকার নীচে অ্যাড-অন বোতামে ক্লিক করুন, তারপর আপনার অ্যাড-অন নির্বাচন করুন। iframe খোলে এবং অ্যাড-অন সংযুক্তি সেটআপ URI লোড করে যা আপনি GWM SDK-এর অ্যাপ কনফিগারেশন পৃষ্ঠায় উল্লেখ করেছেন।

অভিনন্দন! আপনি পরবর্তী ধাপে এগিয়ে যাওয়ার জন্য প্রস্তুত: আপনার অ্যাড-অনে বারবার ভিজিট পরিচালনা করা