Google ব্যবহারকারীর ডেটা অ্যাক্সেস অনুমোদন করুন

প্রমাণীকরণের মাধ্যমে কোনো ব্যক্তির পরিচয় নিশ্চিত করা হয় এবং এটিকে সাধারণত ইউজার সাইন-আপ বা সাইন-ইন বলা হয়। অনুমোদন হলো ডেটা বা রিসোর্সে অ্যাক্সেস মঞ্জুর বা প্রত্যাখ্যান করার প্রক্রিয়া। উদাহরণস্বরূপ, আপনার অ্যাপ কোনো ব্যবহারকারীর গুগল ড্রাইভে অ্যাক্সেস করার জন্য তার অনুমতি চায়।

অ্যাপের প্রয়োজন অনুযায়ী প্রমাণীকরণ এবং অনুমোদন প্রক্রিয়া অবশ্যই দুটি পৃথক ও স্বতন্ত্র ফ্লো হতে হবে।

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

ব্যবহারকারী যখন কোনো নির্দিষ্ট এপিআই-তে অ্যাক্সেসের প্রয়োজন হয় এমন কোনো কাজ করেন, শুধুমাত্র তখনই আপনার প্রয়োজনীয় স্কোপগুলোর জন্য অ্যাক্সেসের অনুরোধ করা উচিত। উদাহরণস্বরূপ, ব্যবহারকারী যখনই ' Save to Drive' বোতামে ট্যাপ করবেন, তখনই তার ড্রাইভ অ্যাক্সেস করার অনুমতির জন্য অনুরোধ করা উচিত।

অনুমোদন এবং প্রমাণীকরণকে আলাদা করার মাধ্যমে, আপনি নতুন ব্যবহারকারীদের উপর অতিরিক্ত চাপ সৃষ্টি করা এড়াতে পারেন, অথবা নির্দিষ্ট অনুমতি কেন চাওয়া হচ্ছে সে বিষয়ে তাদের বিভ্রান্তি থেকে বাঁচাতে পারেন।

প্রমাণীকরণের জন্য, আমরা ক্রেডেনশিয়াল ম্যানেজার এপিআই (Credential Manager API ) ব্যবহার করার পরামর্শ দিই। গুগলে সংরক্ষিত ব্যবহারকারীর ডেটাতে অ্যাক্সেসের প্রয়োজন এমন অ্যাকশনগুলোকে অনুমোদন করার জন্য, আমরা অথরাইজেশনক্লায়েন্ট (AuthorizationClient ) ব্যবহার করার পরামর্শ দিই।

আপনার গুগল ক্লাউড কনসোল প্রজেক্ট সেট আপ করুন

  1. ক্লাউড কনসোলে আপনার প্রজেক্টটি খুলুন, অথবা আপনার কোনো প্রজেক্ট না থাকলে একটি তৈরি করুন।
  2. ব্র্যান্ডিং পেজে সমস্ত তথ্য সম্পূর্ণ ও নির্ভুল আছে কিনা, তা নিশ্চিত করুন।
    1. আপনার অ্যাপের জন্য সঠিক অ্যাপের নাম, অ্যাপ লোগো এবং অ্যাপ হোমপেজ নির্ধারণ করা আছে কিনা তা নিশ্চিত করুন। সাইন আপ করার সময় 'সাইন ইন উইথ গুগল' সম্মতি স্ক্রিনে এবং 'থার্ড-পার্টি অ্যাপস ও সার্ভিসেস' স্ক্রিনে এই মানগুলি ব্যবহারকারীদের দেখানো হবে।
    2. আপনার অ্যাপের গোপনীয়তা নীতি এবং পরিষেবার শর্তাবলীর ইউআরএলগুলো উল্লেখ করেছেন কিনা, তা নিশ্চিত করুন।
  3. ক্লায়েন্টস পেজে , আপনার অ্যাপের জন্য একটি অ্যান্ড্রয়েড ক্লায়েন্ট আইডি তৈরি করুন, যদি আগে থেকে না থাকে। আপনাকে আপনার অ্যাপের প্যাকেজ নেম এবং SHA-1 সিগনেচার উল্লেখ করতে হবে।
    1. ক্লায়েন্ট পৃষ্ঠায় যান।
    2. ক্লায়েন্ট তৈরি করুন -এ ক্লিক করুন।
    3. অ্যান্ড্রয়েড অ্যাপ্লিকেশনটির ধরন নির্বাচন করুন।
    4. OAuth ক্লায়েন্টের জন্য একটি নাম লিখুন। ক্লায়েন্টকে শনাক্ত করার জন্য এই নামটি আপনার প্রোজেক্টের ক্লায়েন্টস পেজে প্রদর্শিত হয়।
    5. আপনার অ্যান্ড্রয়েড অ্যাপের প্যাকেজ নামটি লিখুন। এই মানটি আপনার AndroidManifest.xml ফাইলের <manifest> এলিমেন্টের package অ্যাট্রিবিউটে নির্ধারিত থাকে।
    6. অ্যাপ ডিস্ট্রিবিউশনের SHA-1 সাইনিং সার্টিফিকেট ফিঙ্গারপ্রিন্টটি প্রবেশ করান।
    7. আপনার অ্যাপটি যদি গুগল প্লে-এর অ্যাপ সাইনিং ব্যবহার করে, তাহলে প্লে কনসোলের অ্যাপ সাইনিং পেজ থেকে SHA-1 ফিঙ্গারপ্রিন্টটি কপি করুন।
    8. আপনি যদি নিজের কীস্টোর এবং সাইনিং কী পরিচালনা করেন, তাহলে সার্টিফিকেটের তথ্য সহজে পাঠযোগ্য ফরম্যাটে প্রিন্ট করার জন্য জাভার সাথে অন্তর্ভুক্ত keytool ইউটিলিটিটি ব্যবহার করুন। keytool আউটপুটের ' Certificate fingerprints অংশ থেকে SHA-1 ভ্যালুটি কপি করুন। আরও তথ্যের জন্য Google APIs for Android ডকুমেন্টেশনের 'Authenticating Your Client' অংশটি দেখুন।
    9. (ঐচ্ছিক) আপনার অ্যান্ড্রয়েড অ্যাপ্লিকেশনটির মালিকানা যাচাই করুন
  4. ক্লায়েন্টস পেজে , যদি আগে থেকে তৈরি করা না থাকে, তাহলে একটি নতুন "ওয়েব অ্যাপ্লিকেশন" ক্লায়েন্ট আইডি তৈরি করুন। আপাতত আপনি "অথরাইজড জাভাস্ক্রিপ্ট অরিজিনস" এবং "অথরাইজড রিডাইরেক্ট ইউআরআই" ফিল্ডগুলো উপেক্ষা করতে পারেন। গুগলের অথেন্টিকেশন সার্ভিসের সাথে যোগাযোগের সময় আপনার ব্যাকএন্ড সার্ভারকে শনাক্ত করতে এই ক্লায়েন্ট আইডিটি ব্যবহৃত হবে।
    1. ক্লায়েন্ট পৃষ্ঠায় যান।
    2. ক্লায়েন্ট তৈরি করুন -এ ক্লিক করুন।
    3. ওয়েব অ্যাপ্লিকেশনটির ধরন নির্বাচন করুন।

অ্যাপের মালিকানা যাচাই করুন

অ্যাপ ছদ্মবেশের ঝুঁকি কমাতে আপনি আপনার অ্যাপ্লিকেশনের মালিকানা যাচাই করতে পারেন।

যাচাইকরণ প্রক্রিয়াটি সম্পন্ন করতে, আপনার যদি একটি গুগল প্লে ডেভেলপার অ্যাকাউন্ট থাকে এবং আপনার অ্যাপটি গুগল প্লে কনসোলে নিবন্ধিত থাকে, তবে আপনি সেটি ব্যবহার করতে পারেন। সফল যাচাইকরণের জন্য নিম্নলিখিত শর্তগুলি অবশ্যই পূরণ করতে হবে:

  • আপনি যে অ্যান্ড্রয়েড OAuth ক্লায়েন্টের জন্য যাচাইকরণ সম্পন্ন করছেন, তার প্যাকেজ নাম এবং SHA-1 সাইনিং সার্টিফিকেট ফিঙ্গারপ্রিন্টের সাথে একই প্যাকেজ নাম এবং SHA-1 সাইনিং সার্টিফিকেট ফিঙ্গারপ্রিন্টসহ আপনার একটি অ্যাপ্লিকেশন অবশ্যই গুগল প্লে কনসোলে নিবন্ধিত থাকতে হবে।
  • গুগল প্লে কনসোলে অ্যাপটির জন্য আপনার অবশ্যই অ্যাডমিন অনুমতি থাকতে হবে। গুগল প্লে কনসোলে অ্যাক্সেস ব্যবস্থাপনা সম্পর্কে আরও জানুন

অ্যান্ড্রয়েড ক্লায়েন্টের ' অ্যাপের মালিকানা যাচাই করুন' (Verify App Ownership) বিভাগে, যাচাইকরণ প্রক্রিয়াটি সম্পন্ন করতে 'মালিকানা যাচাই করুন' (Verify Ownership) বোতামটিতে ক্লিক করুন।

যাচাইকরণ সফল হলে, যাচাইকরণ প্রক্রিয়ার সাফল্য নিশ্চিত করতে একটি বিজ্ঞপ্তি প্রদর্শিত হবে। অন্যথায়, একটি ত্রুটির বার্তা দেখানো হবে।

ব্যর্থ যাচাইকরণ ঠিক করতে, নিম্নলিখিতগুলি চেষ্টা করুন:

  • নিশ্চিত করুন যে আপনি যে অ্যাপটি যাচাই করছেন সেটি গুগল প্লে কনসোলে নিবন্ধিত একটি অ্যাপ।
  • গুগল প্লে কনসোলে অ্যাপটির জন্য আপনার অ্যাডমিন অনুমতি আছে কিনা, তা নিশ্চিত করুন।

নির্ভরতা ঘোষণা করুন

আপনার মডিউলের build.gradle ফাইলে, Google Identity Services লাইব্রেরির সর্বশেষ সংস্করণ ব্যবহার করে ডিপেন্ডেন্সিগুলো ঘোষণা করুন।

dependencies {
  // ... other dependencies

  implementation "com.google.android.gms:play-services-auth:21.5.1"
}

ব্যবহারকারীর কার্যকলাপের জন্য প্রয়োজনীয় অনুমতি অনুরোধ করুন

যখনই কোনো ব্যবহারকারী এমন কোনো কাজ করেন যার জন্য অতিরিক্ত স্কোপের প্রয়োজন হয়, তখন AuthorizationClient.authorize() কল করুন। উদাহরণস্বরূপ, যদি কোনো ব্যবহারকারী এমন কোনো কাজ করেন যার জন্য তাদের Drive অ্যাপ স্টোরেজে অ্যাক্সেসের প্রয়োজন হয়, তাহলে নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করুন:

কোটলিন

val requestedScopes: List<Scope> = listOf(DriveScopes.DRIVE_FILE)
val authorizationRequest = AuthorizationRequest.builder()
    .setRequestedScopes(requestedScopes)
    .build()

Identity.getAuthorizationClient(activity)
    .authorize(authorizationRequestBuilder.build())
    .addOnSuccessListener { authorizationResult ->
        if (authorizationResult.hasResolution()) {
            val pendingIntent = authorizationResult.pendingIntent
            // Access needs to be granted by the user
            startAuthorizationIntent.launch(IntentSenderRequest.Builder(pendingIntent!!.intentSender).build())
        } else {
            // Access was previously granted, continue with user action
            saveToDriveAppFolder(authorizationResult);
        }
    }
    .addOnFailureListener { e -> Log.e(TAG, "Failed to authorize", e) }

জাভা

List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_FILE);
AuthorizationRequest authorizationRequest = AuthorizationRequest.builder()
    .setRequestedScopes(requestedScopes)
    .build();

Identity.getAuthorizationClient(activity)
    .authorize(authorizationRequest)
    .addOnSuccessListener(authorizationResult -> {
        if (authorizationResult.hasResolution()) {
            // Access needs to be granted by the user
            startAuthorizationIntent.launch(
                new IntentSenderRequest.Builder(
                    authorizationResult.getPendingIntent().getIntentSender()
                ).build()
            );
        } else {
            // Access was previously granted, continue with user action
            saveToDriveAppFolder(authorizationResult);
        }
    })
    .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));

ActivityResultLauncher সংজ্ঞায়িত করার সময়, নিম্নলিখিত কোড স্নিপেটে দেখানো অনুযায়ী প্রতিক্রিয়াটি পরিচালনা করুন, যেখানে আমরা ধরে নিচ্ছি এটি একটি ফ্র্যাগমেন্টের মধ্যে করা হচ্ছে। কোডটি পরীক্ষা করে দেখে যে প্রয়োজনীয় অনুমতিগুলি সফলভাবে প্রদান করা হয়েছে কিনা এবং তারপরে ব্যবহারকারীর কাজটি সম্পাদন করে।

কোটলিন

private lateinit var startAuthorizationIntent: ActivityResultLauncher<IntentSenderRequest>

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?,
): View? {
    // ...
    startAuthorizationIntent =
        registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->
            try {
                // extract the result
                val authorizationResult = Identity.getAuthorizationClient(requireContext())
                    .getAuthorizationResultFromIntent(activityResult.data)
                // continue with user action
                saveToDriveAppFolder(authorizationResult);
            } catch (e: ApiException) {
                // log exception
            }
        }
}

জাভা

private ActivityResultLauncher<IntentSenderRequest> startAuthorizationIntent;

@Override
public View onCreateView(
    @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ...
startAuthorizationIntent =
    registerForActivityResult(
        new ActivityResultContracts.StartIntentSenderForResult(),
        activityResult -> {
            try {
            // extract the result
            AuthorizationResult authorizationResult =
                Identity.getAuthorizationClient(requireActivity())
                    .getAuthorizationResultFromIntent(activityResult.getData());
            // continue with user action
            saveToDriveAppFolder(authorizationResult);
            } catch (ApiException e) {
            // log exception
            }
        });
}

আপনি যদি সার্ভার সাইডে গুগল এপিআই অ্যাক্সেস করেন, তাহলে একটি অথরাইজেশন কোড পেতে AuthorizationResult থেকে getServerAuthCode() মেথডটি কল করুন, যেটি আপনি আপনার ব্যাকএন্ডে একটি অ্যাক্সেস এবং রিফ্রেশ টোকেনের জন্য বিনিময় করতে পাঠাবেন। আরও জানতে, ব্যবহারকারীর ডেটাতে চলমান অ্যাক্সেস বজায় রাখা দেখুন।

ব্যবহারকারীর ডেটা বা রিসোর্সের অনুমতি প্রত্যাহার করুন

পূর্বে প্রদত্ত অ্যাক্সেস প্রত্যাহার করতে, AuthorizationClient.revokeAccess() কল করুন। উদাহরণস্বরূপ, যদি ব্যবহারকারী আপনার অ্যাপ থেকে তার অ্যাকাউন্ট মুছে ফেলেন, এবং আপনার অ্যাপকে পূর্বে DriveScopes.DRIVE_FILE এ অ্যাক্সেস দেওয়া হয়ে থাকে, তাহলে অ্যাক্সেসটি প্রত্যাহার করতে নিম্নলিখিত কোডটি ব্যবহার করুন:

কোটলিন

val requestedScopes: MutableList<Scope> = mutableListOf(DriveScopes.DRIVE_FILE)
RevokeAccessRequest revokeAccessRequest = RevokeAccessRequest.builder()
    .setAccount(account)
    .setScopes(requestedScopes)
    .build()

Identity.getAuthorizationClient(activity)
    .revokeAccess(revokeAccessRequest)
    .addOnSuccessListener { Log.i(TAG, "Successfully revoked access") }
    .addOnFailureListener { e -> Log.e(TAG, "Failed to revoke access", e) }

জাভা

List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_FILE);
RevokeAccessRequest revokeAccessRequest = RevokeAccessRequest.builder()
    .setAccount(account)
    .setScopes(requestedScopes)
    .build();

Identity.getAuthorizationClient(activity)
    .revokeAccess(revokeAccessRequest)
    .addOnSuccessListener(unused -> Log.i(TAG, "Successfully revoked access"))
    .addOnFailureListener(e -> Log.e(TAG, "Failed to revoke access", e));

টোকেন ক্যাশে পরিষ্কার করুন

সার্ভার থেকে প্রাপ্তির পর OAuth অ্যাক্সেস টোকেনগুলো স্থানীয়ভাবে ক্যাশ করা হয়, যা অ্যাক্সেসকে দ্রুততর করে এবং নেটওয়ার্ক কল কমায়। এই টোকেনগুলোর মেয়াদ শেষ হয়ে গেলে সেগুলো ক্যাশ থেকে স্বয়ংক্রিয়ভাবে মুছে যায়, কিন্তু অন্যান্য কারণেও এগুলো অবৈধ হয়ে যেতে পারে। টোকেন ব্যবহার করার সময় যদি আপনি একটি IllegalStateException পান, তাহলে স্থানীয় ক্যাশটি পরিষ্কার করুন, যাতে অ্যাক্সেস টোকেনের জন্য পরবর্তী অনুমোদনের অনুরোধটি OAuth সার্ভারে যায়। নিম্নলিখিত কোড স্নিপেটটি স্থানীয় ক্যাশ থেকে invalidAccessToken টি মুছে ফেলে:

কোটলিন

Identity.getAuthorizationClient(activity)
    .clearToken(ClearTokenRequest.builder().setToken(invalidAccessToken).build())
    .addOnSuccessListener { Log.i(TAG, "Successfully removed the token from the cache") }
    .addOnFailureListener{ e -> Log.e(TAG, "Failed to clear token", e) }

জাভা

Identity.getAuthorizationClient(activity)
    .clearToken(ClearTokenRequest.builder().setToken(invalidAccessToken).build())
    .addOnSuccessListener(unused -> Log.i(TAG, "Successfully removed the token from the cache"))
    .addOnFailureListener(e -> Log.e(TAG, "Failed to clear the token cache", e));

অনুমোদনের সময় ব্যবহারকারীর তথ্য সংগ্রহ করুন

অনুমোদন প্রতিক্রিয়ায় ব্যবহৃত ব্যবহারকারী অ্যাকাউন্ট সম্পর্কে কোনো তথ্য থাকে না; প্রতিক্রিয়াটিতে শুধুমাত্র অনুরোধ করা স্কোপগুলোর জন্য একটি টোকেন থাকে। উদাহরণস্বরূপ, কোনো ব্যবহারকারীর গুগল ড্রাইভ অ্যাক্সেস করার জন্য অ্যাক্সেস টোকেন পাওয়ার প্রতিক্রিয়াটি ব্যবহারকারীর নির্বাচিত অ্যাকাউন্টের পরিচয় প্রকাশ করে না, যদিও এটি ব্যবহারকারীর ড্রাইভের ফাইলগুলো অ্যাক্সেস করতে ব্যবহার করা যেতে পারে। ব্যবহারকারীর নাম বা ইমেলের মতো তথ্য পেতে, আপনার কাছে নিম্নলিখিত বিকল্পগুলো রয়েছে:

  • অনুমোদনের জন্য অনুরোধ করার আগে ক্রেডেনশিয়াল ম্যানেজার এপিআই ব্যবহার করে ব্যবহারকারীকে তাদের গুগল অ্যাকাউন্ট দিয়ে সাইন ইন করান। ক্রেডেনশিয়াল ম্যানেজার থেকে প্রাপ্ত প্রমাণীকরণ প্রতিক্রিয়ায় ব্যবহারকারীর ইমেল ঠিকানার মতো তথ্য অন্তর্ভুক্ত থাকে এবং এটি অ্যাপের ডিফল্ট অ্যাকাউন্ট হিসেবে নির্বাচিত অ্যাকাউন্টটিকে সেট করে দেয়; প্রয়োজন হলে, আপনি আপনার অ্যাপে এই অ্যাকাউন্টটি ট্র্যাক করতে পারেন। পরবর্তী কোনো অনুমোদনের অনুরোধে অ্যাকাউন্টটি ডিফল্ট হিসেবে ব্যবহৃত হয় এবং অনুমোদন প্রক্রিয়ার অ্যাকাউন্ট নির্বাচনের ধাপটি এড়িয়ে যায়। অনুমোদনের জন্য একটি ভিন্ন অ্যাকাউন্ট ব্যবহার করতে, ‘ডিফল্ট নয় এমন অ্যাকাউন্ট থেকে অনুমোদন’ দেখুন।

  • আপনার অনুমোদন অনুরোধে, আপনার কাঙ্ক্ষিত স্কোপগুলোর (যেমন, Drive scope ) পাশাপাশি userinfo , profile , এবং openid স্কোপগুলোর জন্যও অনুরোধ করুন। একটি অ্যাক্সেস টোকেন ফেরত আসার পর, আপনার পছন্দের HTTP লাইব্রেরি ব্যবহার করে এবং হেডারে প্রাপ্ত অ্যাক্সেস টোকেনটি অন্তর্ভুক্ত করে OAuth userinfo এন্ডপয়েন্টে (https://www.googleapis.com/oauth2/v3/userinfo) একটি GET HTTP অনুরোধ পাঠিয়ে ব্যবহারকারীর তথ্য সংগ্রহ করুন, যা নিম্নলিখিত curl কমান্ডের সমতুল্য:

    curl -X GET \ "https://www.googleapis.com/oauth2/v1/userinfo?alt=json" \ -H "Authorization: Bearer $TOKEN"
    

    প্রতিক্রিয়াটি হলো UserInfo , যা অনুরোধ করা স্কোপগুলোর মধ্যে সীমাবদ্ধ এবং JSON ফরম্যাটে বিন্যস্ত।

একটি নন-ডিফল্ট অ্যাকাউন্ট থেকে অনুমোদন

আপনি যদি প্রমাণীকরণের জন্য ক্রেডেনশিয়াল ম্যানেজার ব্যবহার করেন এবং AuthorizationClient.authorize() চালান, তাহলে আপনার অ্যাপের ডিফল্ট অ্যাকাউন্টটি ব্যবহারকারীর নির্বাচিত অ্যাকাউন্টে সেট হয়ে যায়। এর মানে হলো, পরবর্তী যেকোনো অনুমোদনের জন্য এই ডিফল্ট অ্যাকাউন্টটিই ব্যবহৃত হবে। অ্যাকাউন্ট সিলেক্টরটি দেখাতে বাধ্য করার জন্য, ক্রেডেনশিয়াল ম্যানেজারের clearCredentialState() API ব্যবহার করে ব্যবহারকারীকে অ্যাপ থেকে সাইন আউট করুন।

ব্যবহারকারীর ডেটাতে নিরবচ্ছিন্ন প্রবেশাধিকার বজায় রাখুন

আপনার অ্যাপ থেকে ব্যবহারকারীর ডেটা অ্যাক্সেস করার প্রয়োজন হলে, AuthorizationClient.authorize() একবার কল করুন; পরবর্তী সেশনগুলিতে, এবং যতক্ষণ না ব্যবহারকারী প্রদত্ত অনুমতিগুলি সরিয়ে নিচ্ছেন, ততক্ষণ পর্যন্ত ব্যবহারকারীর কোনো হস্তক্ষেপ ছাড়াই আপনার উদ্দেশ্য পূরণের জন্য একটি অ্যাক্সেস টোকেন পেতে একই পদ্ধতিটি কল করুন। অন্যদিকে, যদি আপনার ব্যাকএন্ড সার্ভার থেকে অফলাইন মোডে ব্যবহারকারীর ডেটা অ্যাক্সেস করার প্রয়োজন হয়, তাহলে আপনাকে "রিফ্রেশ টোকেন" নামক একটি ভিন্ন ধরনের টোকেনের জন্য অনুরোধ করতে হবে।

অ্যাক্সেস টোকেনগুলো ইচ্ছাকৃতভাবে স্বল্পস্থায়ী করে ডিজাইন করা হয় এবং এগুলোর মেয়াদ এক ঘণ্টা। যদি কোনো অ্যাক্সেস টোকেন হস্তগত বা অরক্ষিত হয়ে পড়ে, তবে এর সীমিত বৈধতার সময়সীমা সম্ভাব্য অপব্যবহারকে কমিয়ে দেয়। মেয়াদ শেষ হয়ে গেলে টোকেনটি অবৈধ হয়ে যায় এবং এটি ব্যবহারের যেকোনো প্রচেষ্টা রিসোর্স সার্ভার দ্বারা প্রত্যাখ্যাত হয়। যেহেতু অ্যাক্সেস টোকেনগুলো স্বল্পস্থায়ী, তাই সার্ভারগুলো ব্যবহারকারীর ডেটাতে নিরবচ্ছিন্ন অ্যাক্সেস বজায় রাখার জন্য রিফ্রেশ টোকেন ব্যবহার করে। রিফ্রেশ টোকেন হলো দীর্ঘ মেয়াদের টোকেন, যা পুরোনো অ্যাক্সেস টোকেনের মেয়াদ শেষ হয়ে গেলে কোনো ব্যবহারকারীর হস্তক্ষেপ ছাড়াই ক্লায়েন্ট কর্তৃক অথরাইজেশন সার্ভার থেকে একটি স্বল্পস্থায়ী অ্যাক্সেস টোকেনের অনুরোধ করার জন্য ব্যবহৃত হয়।

একটি রিফ্রেশ টোকেন পেতে হলে, আপনাকে প্রথমে আপনার অ্যাপের অথরাইজেশন ধাপে "অফলাইন অ্যাক্সেস" চেয়ে একটি অথ কোড (বা অথরাইজেশন কোড) সংগ্রহ করতে হবে এবং তারপর আপনার সার্ভারে সেই অথ কোডটি একটি রিফ্রেশ টোকেনের জন্য বিনিময় করতে হবে। দীর্ঘস্থায়ী রিফ্রেশ টোকেনগুলো আপনার সার্ভারে নিরাপদে সংরক্ষণ করা অত্যন্ত গুরুত্বপূর্ণ, কারণ এগুলো বারবার নতুন অ্যাক্সেস টোকেন পাওয়ার জন্য ব্যবহার করা যেতে পারে। তাই, নিরাপত্তাজনিত কারণে ডিভাইসে রিফ্রেশ টোকেন সংরক্ষণ করাকে কঠোরভাবে নিরুৎসাহিত করা হয়। এর পরিবর্তে, এগুলো অ্যাপের ব্যাকএন্ড সার্ভারে সংরক্ষণ করা উচিত, যেখানে অ্যাক্সেস টোকেনের জন্য বিনিময় প্রক্রিয়াটি সম্পন্ন হয়।

আপনার অ্যাপের ব্যাকএন্ড সার্ভারে অথ কোডটি পাঠানোর পর, আপনি অ্যাকাউন্ট অথরাইজেশন গাইডের ধাপগুলো অনুসরণ করে সেটিকে সার্ভারে একটি স্বল্পস্থায়ী অ্যাক্সেস টোকেন এবং একটি দীর্ঘস্থায়ী রিফ্রেশ টোকেনের জন্য বিনিময় করতে পারেন। এই বিনিময়টি শুধুমাত্র আপনার অ্যাপের ব্যাকএন্ডেই হওয়া উচিত।

কোটলিন

// Ask for offline access during the first authorization request
val authorizationRequest = AuthorizationRequest.builder()
    .setRequestedScopes(requestedScopes)
    .requestOfflineAccess(serverClientId)
    .build()

Identity.getAuthorizationClient(activity)
    .authorize(authorizationRequest)
    .addOnSuccessListener { authorizationResult ->
        startAuthorizationIntent.launch(IntentSenderRequest.Builder(
            pendingIntent!!.intentSender
        ).build())
    }
    .addOnFailureListener { e -> Log.e(TAG, "Failed to authorize", e) }

জাভা

// Ask for offline access during the first authorization request
AuthorizationRequest authorizationRequest = AuthorizationRequest.builder()
    .setRequestedScopes(requestedScopes)
    .requestOfflineAccess(serverClientId)
    .build();

Identity.getAuthorizationClient(getContext())
    .authorize(authorizationRequest)
    .addOnSuccessListener(authorizationResult -> {
        startAuthorizationIntent.launch(
            new IntentSenderRequest.Builder(
                authorizationResult.getPendingIntent().getIntentSender()
            ).build()
        );
    })
    .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize"));

নিম্নলিখিত কোড স্নিপেটটি ধরে নেয় যে অনুমোদন প্রক্রিয়াটি একটি ফ্র্যাগমেন্ট থেকে শুরু করা হয়েছে।

কোটলিন

private lateinit var startAuthorizationIntent: ActivityResultLauncher<IntentSenderRequest>

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?,
): View? {
    // ...
    startAuthorizationIntent =
        registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->
            try {
                val authorizationResult = Identity.getAuthorizationClient(requireContext())
                    .getAuthorizationResultFromIntent(activityResult.data)
                // short-lived access token
                accessToken = authorizationResult.accessToken
                // store the authorization code used for getting a refresh token safely to your app's backend server
                val authCode: String = authorizationResult.serverAuthCode
                storeAuthCodeSafely(authCode)
            } catch (e: ApiException) {
                // log exception
            }
        }
}

জাভা

private ActivityResultLauncher<IntentSenderRequest> startAuthorizationIntent;

@Override
public View onCreateView(
    @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // ...
    startAuthorizationIntent =
        registerForActivityResult(
            new ActivityResultContracts.StartIntentSenderForResult(),
            activityResult -> {
                try {
                    AuthorizationResult authorizationResult =
                        Identity.getAuthorizationClient(requireActivity())
                            .getAuthorizationResultFromIntent(activityResult.getData());
                    // short-lived access token
                    accessToken = authorizationResult.getAccessToken();
                    // store the authorization code used for getting a refresh token safely to your app's backend server
                    String authCode = authorizationResult.getServerAuthCode()
                    storeAuthCodeSafely(authCode);
                } catch (ApiException e) {
                    // log exception
                }
            });
}