OAuth 2.0 और Java के लिए Google OAuth क्लाइंट लाइब्रेरी

खास जानकारी

मकसद: इस दस्तावेज़ में, OAuth 2.0 के उन जेनरिक फ़ंक्शन के बारे में बताया गया है जो यहां दिए गए हैं Google OAuth क्लाइंट लाइब्रेरी का इस्तेमाल कर सकते हैं. इन फ़ंक्शन का इस्तेमाल इन कामों के लिए किया जा सकता है सभी इंटरनेट सेवाओं के लिए प्रमाणीकरण और प्राधिकरण.

GoogleCredential का इस्तेमाल करके OAuth 2.0 की अनुमति देने के बारे में निर्देश Google सेवाएं, देखें Java के लिए Google API क्लाइंट लाइब्रेरी के साथ OAuth 2.0 का इस्तेमाल करना.

खास जानकारी: OAuth 2.0, असली उपयोगकर्ताओं को क्लाइंट को सुरक्षित रूप से अनुमति देने के लिए स्टैंडर्ड स्पेसिफ़िकेशन सुरक्षित सर्वर-साइड संसाधनों को ऐक्सेस करने के लिए एक ऐप्लिकेशन है. इसके अलावा, OAuth 2.0 बेयरर टोकन स्पेसिफ़िकेशन में यह बताया गया है कि किसी ऐक्सेस का इस्तेमाल करके, सुरक्षित किए गए संसाधनों को कैसे ऐक्सेस किया जा सकता है असली उपयोगकर्ता को अनुमति देने की प्रक्रिया के दौरान दिया गया टोकन.

जानकारी के लिए, इन पैकेज के Javadoc दस्तावेज़ देखें:

क्लाइंट रजिस्ट्रेशन

Java के लिए Google OAuth क्लाइंट लाइब्रेरी का इस्तेमाल करने से पहले, आपको क्लाइंट आईडी पाने के लिए, अपने ऐप्लिकेशन को अनुमति देने वाले सर्वर के साथ रजिस्टर करें और क्लाइंट सीक्रेट. (इस प्रक्रिया के बारे में सामान्य जानकारी के लिए, क्लाइंट रजिस्ट्रेशन के बारे में जानकारी.)

क्रेडेंशियल और क्रेडेंशियल स्टोर

क्रेडेंशियल का इस्तेमाल करके सुरक्षित संसाधनों को ऐक्सेस करने के लिए, एक थ्रेड से सुरक्षित OAuth 2.0 हेल्पर क्लास है ऐक्सेस टोकन. रीफ़्रेश टोकन का इस्तेमाल करने पर, Credential ऐक्सेस को भी रीफ़्रेश करता है टोकन, जब ऐक्सेस टोकन की समय-सीमा रीफ़्रेश टोकन का इस्तेमाल करके खत्म हो जाती है. उदाहरण के लिए, अगर पास पहले से ही ऐक्सेस टोकन होता है, तो नीचे दिए गए तरीके से अनुरोध किया जा सकता है:

  public static HttpResponse executeGet(
      HttpTransport transport, JsonFactory jsonFactory, String accessToken, GenericUrl url)
      throws IOException {
    Credential credential =
        new Credential(BearerToken.authorizationHeaderAccessMethod()).setAccessToken(accessToken);
    HttpRequestFactory requestFactory = transport.createRequestFactory(credential);
    return requestFactory.buildGetRequest(url).execute();
  }

ज़्यादातर ऐप्लिकेशन को क्रेडेंशियल के ऐक्सेस टोकन को बनाए रखना होगा और टोकन को रीफ़्रेश करें, ताकि आने वाले समय में आपको अनुमति न मिले. ब्राउज़र में पेज खोलें. कॉन्टेंट बनाने CredentialStore इस लाइब्रेरी में लागू करने की सुविधा पर रोक लगा दी गई है और इसे आने वाले समय में हटा दिया जाएगा रिलीज़. दूसरा विकल्प यह है कि DataStoreFactory और DataStore वाले इंटरफ़ेस StoredCredential, जो Java के लिए Google एचटीटीपी क्लाइंट लाइब्रेरी.

लाइब्रेरी से मिले इनमें से किसी एक तरीके का इस्तेमाल किया जा सकता है:

  • JdoDataStoreFactory JDO का इस्तेमाल करके क्रेडेंशियल को बनाए रखता है.
  • AppEngineDataStoreFactory Google App Engine Data Store API का उपयोग करके क्रेडेंशियल बना रहता है.
  • MemoryDataStoreFactory "नियमित तौर पर" क्रेडेंशियल, मेमोरी में सेव किए जाते हैं, जो सिर्फ़ कुछ समय के लिए काम आते हैं स्टोरेज की सुविधा को हमेशा के लिए स्टोर कर सकते हैं.
  • FileDataStoreFactory किसी फ़ाइल में क्रेडेंशियल बना रहता है.

Google App Engine उपयोगकर्ता:

AppEngineCredentialStore का इस्तेमाल नहीं किया जा सकता और इसे हटाया जा रहा है.

हमारी सलाह है कि आप AppEngineDataStoreFactory StoredCredential का इस्तेमाल करके. अगर आपने क्रेडेंशियल को पुराने तरीके से सेव किया है, तो अतिरिक्त हेल्पर तरीकों का इस्तेमाल किया जा सकता है migrateTo(AppEngineDataStoreFactory) या migrateTo(DataStore) माइग्रेट करने के लिए.

DataStoreCredentialRefreshListener का इस्तेमाल करें और इसे क्रेडेंशियल के लिए सेट करने के लिए, GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener).

ऑथराइज़ेशन कोड का फ़्लो

असली उपयोगकर्ता को आपका आवेदन देने की अनुमति देने के लिए, ऑथराइज़ेशन कोड के फ़्लो का इस्तेमाल करें उनके सुरक्षित डेटा को ऐक्सेस कर सकें. इस फ़्लो के प्रोटोकॉल की जानकारी इसमें दी गई है ऑथराइज़ेशन कोड ग्रांट की खास बातें.

इस फ़्लो को इसका इस्तेमाल करके लागू किया जाता है AuthorizationCodeFlow. चरण इस प्रकार हैं:

  • असली उपयोगकर्ता आपके ऐप्लिकेशन में लॉग इन करता है. आपको उस उपयोगकर्ता को एक उपयोगकर्ता आईडी होता है, जो आपके ऐप्लिकेशन के लिए अद्वितीय होता है.
  • कॉल करें AuthorizationCodeFlow.loadCredential(String), उसका इस्तेमाल करके, यह पता लगाया जा सकता है कि उपयोगकर्ता के क्रेडेंशियल पहले से जानते हैं या नहीं. अगर ऐसा है, तो आपका काम हो गया.
  • अगर नहीं, तो AuthorizationCodeFlow.newAuthorizationUrl() को कॉल करें और असली उपयोगकर्ता के ब्राउज़र को अनुमति वाले पेज पर भेजें, जहां वे आपके ऐप्लिकेशन को उनके सुरक्षित डेटा का ऐक्सेस दे.
  • इसके बाद, वेब ब्राउज़र एक "कोड" के साथ दूसरे वेबलिंक पर भेजता है क् वेरी ऐक्सेस टोकन का अनुरोध करने के लिए, इस्तेमाल किया जा सकने वाला पैरामीटर AuthorizationCodeFlow.newTokenRequest(String).
  • इस्तेमाल की जाने वाली चीज़ें AuthorizationCodeFlow.createAndStore क्रेडेंशियल(TokenResponse, स्ट्रिंग) को स्टोर करने और सुरक्षित संसाधनों को ऐक्सेस करने के लिए क्रेडेंशियल पाने के लिए.

इसके अलावा, अगर इसका इस्तेमाल नहीं किया जा रहा है, AuthorizationCodeFlow, नीचे दिए गए लेवल की क्लास का इस्तेमाल किया जा सकता है:

  • DataStore.get(String) का इस्तेमाल करें का इस्तेमाल करें.
  • AuthorizationCodeRequestUrl का इस्तेमाल करें ब्राउज़र को अनुमति वाले पेज पर ले जाने के लिए.
  • AuthorizationCodeResponseUrl का इस्तेमाल करें का इस्तेमाल करें.
  • AuthorizationCodeTokenRequest का इस्तेमाल करें ऐक्सेस टोकन और रीफ़्रेश टोकन का अनुरोध करने के लिए.
  • नया क्रेडेंशियल बनाएं और उसे DataStore.set(String, V) का इस्तेमाल करके सेव करें.
  • क्रेडेंशियल का इस्तेमाल करके सुरक्षित संसाधनों को ऐक्सेस करना. ऐक्सेस टोकन की समयसीमा खत्म होने पर, वे रीफ़्रेश टोकन का इस्तेमाल करके अपने-आप रीफ़्रेश हो जाते हैं. ऐसा तब होता है, जब लागू. कृपया DataStoreCredentialRefreshListener और इसे क्रेडेंशियल के लिए सेट करने के लिए, Credential.Builder.addRefreshListener(CredentialRefreshListener).

सर्वलेट ऑथराइज़ेशन कोड का फ़्लो

यह लाइब्रेरी काफ़ी आसान बनाने के लिए सर्वलेट हेल्पर क्लास उपलब्ध कराती है इस्तेमाल के सामान्य उदाहरणों के लिए, ऑथराइज़ेशन कोड फ़्लो. आप सिर्फ़ सटीक सब-क्लास देते हैं में से AbstractAuthorizationCodeServlet और AbstractAuthorizationCodeCallbackServlet (google-oauth-client-servlet से) से लिए गए हों और उन्हें अपनी web.xml फ़ाइल में जोड़ें. ध्यान दें कि आपको अब भी उपयोगकर्ता का ध्यान रखना होगा अपने वेब ऐप्लिकेशन के लिए लॉगिन करें और उपयोगकर्ता आईडी एक्सट्रैक्ट करें.

कोड का नमूना:

public class ServletSample extends AbstractAuthorizationCodeServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    // do stuff
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(),
        new NetHttpTransport(),
        new JacksonFactory(),
        new GenericUrl("https://server.example.com/token"),
        new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"),
        "s6BhdRkqt3",
        "https://server.example.com/authorize").setCredentialDataStore(
            StoredCredential.getDefaultDataStore(
                new FileDataStoreFactory(new File("datastoredir"))))
        .build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

public class ServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet {

  @Override
  protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
      throws ServletException, IOException {
    resp.sendRedirect("/");
  }

  @Override
  protected void onError(
      HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
      throws ServletException, IOException {
    // handle error
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(),
        new NetHttpTransport(),
        new JacksonFactory(),
        new GenericUrl("https://server.example.com/token"),
        new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"),
        "s6BhdRkqt3",
        "https://server.example.com/authorize").setCredentialDataStore(
            StoredCredential.getDefaultDataStore(
                new FileDataStoreFactory(new File("datastoredir"))))
        .build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

Google App Engine का ऑथराइज़ेशन कोड का फ़्लो

App Engine पर ऑथराइज़ेशन कोड का फ़्लो, सर्वलेट की तरह होता है ऑथराइज़ेशन कोड के फ़्लो का इस्तेमाल न करें, क्योंकि हम Google App Engine के उपयोगकर्ताओं का Java API. उपयोगकर्ताओं का Java API चालू करने के लिए, उपयोगकर्ता को लॉग इन करना ज़रूरी है; इसके लिए अगर उपयोगकर्ता पहले से ही लॉगिन पेज पर नहीं हैं, तो उन्हें लॉगिन पेज पर रीडायरेक्ट करने के बारे में जानकारी लॉग इन किया है, तो देखें सुरक्षा और पुष्टि करना (web.xml में).

सर्वलेट केस से मुख्य अंतर यह है कि कंक्रीट इसकी सब-क्लास AbstractAppEngineAuthorizationCodeServlet और AbstractAppEngineAuthorizationCodeCallbackServlet (google-oauth-client-appengine से). वे उपयोगकर्ता Java API का इस्तेमाल करके, ऐब्स्ट्रैक्ट सर्वलेट क्लास को बढ़ाते हैं और आपके लिए getUserId तरीका लागू करते हैं. Google App Engine Data Store API का इस्तेमाल करके, क्रेडेंशियल को बनाए रखने के लिए, AppEngineDataStoreFactory से (Java के लिए Google एचटीटीपी क्लाइंट लाइब्रेरी का इस्तेमाल करना अच्छा विकल्प है.

कोड का नमूना:

public class AppEngineSample extends AbstractAppEngineAuthorizationCodeServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    // do stuff
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(),
        new UrlFetchTransport(),
        new JacksonFactory(),
        new GenericUrl("https://server.example.com/token"),
        new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"),
        "s6BhdRkqt3",
        "https://server.example.com/authorize").setCredentialStore(
            StoredCredential.getDefaultDataStore(AppEngineDataStoreFactory.getDefaultInstance()))
        .build();
  }
}

public class AppEngineCallbackSample extends AbstractAppEngineAuthorizationCodeCallbackServlet {

  @Override
  protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
      throws ServletException, IOException {
    resp.sendRedirect("/");
  }

  @Override
  protected void onError(
      HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
      throws ServletException, IOException {
    // handle error
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(),
        new UrlFetchTransport(),
        new JacksonFactory(),
        new GenericUrl("https://server.example.com/token"),
        new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"),
        "s6BhdRkqt3",
        "https://server.example.com/authorize").setCredentialStore(
            StoredCredential.getDefaultDataStore(AppEngineDataStoreFactory.getDefaultInstance()))
        .build();
  }
}

कमांड-लाइन ऑथराइज़ेशन कोड फ़्लो

उदाहरण के तौर पर दिया गया कोड यहां से लिया गया है dailymotion-cmdline-sample:

/** Authorizes the installed application to access user's protected data. */
private static Credential authorize() throws Exception {
  OAuth2ClientCredentials.errorIfNotSpecified();
  // set up authorization code flow
  AuthorizationCodeFlow flow = new AuthorizationCodeFlow.Builder(BearerToken
      .authorizationHeaderAccessMethod(),
      HTTP_TRANSPORT,
      JSON_FACTORY,
      new GenericUrl(TOKEN_SERVER_URL),
      new ClientParametersAuthentication(
          OAuth2ClientCredentials.API_KEY, OAuth2ClientCredentials.API_SECRET),
      OAuth2ClientCredentials.API_KEY,
      AUTHORIZATION_SERVER_URL).setScopes(Arrays.asList(SCOPE))
      .setDataStoreFactory(DATA_STORE_FACTORY).build();
  // authorize
  LocalServerReceiver receiver = new LocalServerReceiver.Builder().setHost(
      OAuth2ClientCredentials.DOMAIN).setPort(OAuth2ClientCredentials.PORT).build();
  return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
}

private static void run(HttpRequestFactory requestFactory) throws IOException {
  DailyMotionUrl url = new DailyMotionUrl("https://api.dailymotion.com/videos/favorites");
  url.setFields("id,tags,title,url");

  HttpRequest request = requestFactory.buildGetRequest(url);
  VideoFeed videoFeed = request.execute().parseAs(VideoFeed.class);
  ...
}

public static void main(String[] args) {
  ...
  DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
  final Credential credential = authorize();
  HttpRequestFactory requestFactory =
      HTTP_TRANSPORT.createRequestFactory(new HttpRequestInitializer() {
        @Override
        public void initialize(HttpRequest request) throws IOException {
          credential.initialize(request);
          request.setParser(new JsonObjectParser(JSON_FACTORY));
        }
      });
  run(requestFactory);
  ...
}

ब्राउज़र पर आधारित क्लाइंट फ़्लो

ये ब्राउज़र पर आधारित क्लाइंट फ़्लो के सामान्य चरण हैं जिन्हें इंप्लिसिट ग्रांट की खास बातें:

  • BrowserClientRequestUrl का इस्तेमाल करके, असली उपयोगकर्ता के ब्राउज़र को अनुमति देने वाले पेज पर रीडायरेक्ट करते हैं, जहां असली उपयोगकर्ता यह कर सकता है: आपके ऐप्लिकेशन को उनके सुरक्षित डेटा का ऐक्सेस दें.
  • यूआरएल में मिले ऐक्सेस टोकन को प्रोसेस करने के लिए JavaScript ऐप्लिकेशन का इस्तेमाल करें रीडायरेक्ट यूआरआई पर फ़्रैगमेंट जो ऑथराइज़ेशन सर्वर के साथ रजिस्टर है.

वेब ऐप्लिकेशन के इस्तेमाल का सैंपल:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
  String url = new BrowserClientRequestUrl(
      "https://server.example.com/authorize", "s6BhdRkqt3").setState("xyz")
      .setRedirectUri("https://client.example.com/cb").build();
  response.sendRedirect(url);
}

ऐसे ऐक्सेस टोकन का पता लगाना जिसकी समयसीमा खत्म हो चुकी है

OAuth 2.0 बेयरर स्पेसिफ़िकेशन के मुताबिक, जब सर्वर को ऐसे सुरक्षित संसाधन को ऐक्सेस करने के लिए कॉल किया जाता है जिसके ऐक्सेस की समयसीमा खत्म हो गई हो टोकन नहीं है, तो सर्वर आम तौर पर एक HTTP 401 Unauthorized स्थिति कोड के साथ जवाब देता है जैसे:

   HTTP/1.1 401 Unauthorized
   WWW-Authenticate: Bearer realm="example",
                     error="invalid_token",
                     error_description="The access token expired"

हालांकि, निर्देशों में काफ़ी ज़्यादा छूट दिखती है. इसके लिए जानकारी के लिए, OAuth 2.0 कंपनी का दस्तावेज़ देखें.

इसका एक वैकल्पिक तरीका यह है कि आपexpires_in ऐक्सेस टोकन रिस्पॉन्स. यह दिए गए ऐक्सेस टोकन के सेकंड में लाइफ़टाइम तय करता है, जो कि आम तौर पर एक घंटे में. हालांकि, हो सकता है कि ऐक्सेस टोकन की समयसीमा आपकी सदस्यता रद्द नहीं होती है, तो हो सकता है कि सर्वर ऐक्सेस की अनुमति देता रहे. इसलिए, हमने आम तौर पर, हमारा सुझाव है कि आप गड़बड़ी के मैसेज के बजाय, 401 Unauthorized स्टेटस कोड का इंतज़ार करें यह मानते हुए कि टोकन की समयसीमा खत्म हो चुकी है. इसके अलावा, आपके पास ये विकल्प हैं ऐक्सेस टोकन की समयसीमा खत्म होने से कुछ समय पहले, उसे रीफ़्रेश करने की कोशिश करें. अगर टोकन सर्वर उपलब्ध नहीं है, जब तक आपको 401 नहीं मिल जाता, तब तक ऐक्सेस टोकन का इस्तेमाल करें. यह में डिफ़ॉल्ट रूप से इसी कार्यनीति का उपयोग किया जाता है: क्रेडेंशियल.

दूसरा विकल्प यह है कि हर अनुरोध से पहले नया ऐक्सेस टोकन पाएं. हालांकि, टोकन सर्वर को हर बार एक अतिरिक्त एचटीटीपी अनुरोध भेजना पड़ता है. इसलिए, ऐसा हो सकता है कि की स्पीड और नेटवर्क के इस्तेमाल के मामले में अच्छा विकल्प नहीं है. आम तौर पर, ऐक्सेस टोकन सेव करना होता है में सुरक्षित और स्थायी स्टोरेज मिलता है, ताकि ऐप्लिकेशन के नए ऐक्सेस के अनुरोधों को कम किया जा सके टोकन. (लेकिन इंस्टॉल किए गए ऐप्लिकेशन के लिए, सुरक्षित जगह एक मुश्किल समस्या है.)

ध्यान दें कि ऐक्सेस टोकन, समयसीमा खत्म होने की वजह से अमान्य हो सकता है. उदाहरण के लिए, यदि उपयोगकर्ता ने स्पष्ट रूप से टोकन रद्द कर दिया है, तो गड़बड़ी को ठीक करने वाला कोड मज़बूत है. जब आपको पता चल जाए कि टोकन मौजूद नहीं है मान्य है, उदाहरण के लिए अगर उसकी समयसीमा खत्म हो गई हो या उसे निरस्त कर दिया गया हो, तो आपको टोकन शामिल करें. उदाहरण के लिए, Android पर आपको AccountManager.invalidateAuthToken.