खास जानकारी
मकसद: इस दस्तावेज़ में, Java के लिए Google OAuth क्लाइंट लाइब्रेरी की ओर से उपलब्ध कराए गए सामान्य OAuth 2.0 फ़ंक्शन के बारे में बताया गया है. इन फ़ंक्शन का इस्तेमाल, इंटरनेट की किसी भी सेवा के लिए पुष्टि करने और अनुमति देने के लिए किया जा सकता है.
Google की सेवाओं पर OAuth 2.0 की अनुमति देने के लिए, GoogleCredential
का इस्तेमाल करने से जुड़े निर्देशों के लिए, Java के लिए Google API क्लाइंट लाइब्रेरी के साथ OAuth 2.0 का इस्तेमाल करना देखें.
खास जानकारी: OAuth 2.0, एक स्टैंडर्ड स्पेसिफ़िकेशन है. इससे असली उपयोगकर्ताओं को, क्लाइंट ऐप्लिकेशन को सुरक्षित सर्वर साइड रिसॉर्स ऐक्सेस करने की अनुमति देने की अनुमति मिलती है. इसके अलावा, OAuth 2.0 के तहत मिलने वाले, पासकोड के तौर पर इस्तेमाल होने वाले टोकन के स्पेसिफ़िकेशन में, उन संसाधनों को ऐक्सेस करने का तरीका बताया गया है जिन्हें ऐक्सेस करने के लिए, एंड-यूज़र की अनुमति की प्रोसेस के दौरान ऐक्सेस टोकन दिया गया है.
ज़्यादा जानकारी के लिए, इन पैकेज के लिए Javadoc दस्तावेज़ देखें:
- com.google.api.client.auth.oauth2 (google-oauth-client से)
- com.google.api.client.extensions.servlet.auth.oauth2 (google-oauth-client-servlet से)
- com.google.api.client.extensions.appengine.auth.oauth2 (from google-oauth-client-appengine)
क्लाइंट रजिस्ट्रेशन
Java के लिए Google OAuth क्लाइंट लाइब्रेरी का इस्तेमाल करने से पहले, आपको क्लाइंट आईडी और क्लाइंट सीक्रेट पाने के लिए, अपने ऐप्लिकेशन को अनुमति देने वाले सर्वर के साथ रजिस्टर करना पड़ सकता है. (इस प्रोसेस के बारे में सामान्य जानकारी के लिए, क्लाइंट रजिस्टर करने की खास बातें देखें.)
क्रेडेंशियल और क्रेडेंशियल स्टोर
Credential, एक थ्रेड-सेफ़ 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 का इस्तेमाल अब नहीं किया जा सकता. इसे हटा दिया जा रहा है.
हमारा सुझाव है कि आप StoredCredential के साथ AppEngineDataStoreFactory का इस्तेमाल करें. अगर आपने क्रेडेंशियल पुराने तरीके से सेव किए हैं, तो माइग्रेट करने के लिए, जोड़े गए सहायक तरीकों का इस्तेमाल किया जा सकता है. जैसे, migrateTo(AppEngineDataStoreFactory) या migrateTo(DataStore).
DataStoreCredentialRefreshListener का इस्तेमाल करें और GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener) का इस्तेमाल करके, इसे क्रेडेंशियल के लिए सेट करें.
ऑथराइज़ेशन कोड का फ़्लो
असली उपयोगकर्ता को आपके ऐप्लिकेशन को अपने सुरक्षित डेटा का ऐक्सेस देने की अनुमति देने के लिए, ऑथराइज़ेशन कोड के फ़्लो का इस्तेमाल करें. इस फ़्लो के लिए प्रोटोकॉल, ऑथराइज़ेशन कोड देने की खास जानकारी में बताया गया है.
इस फ़्लो को AuthorizationCodeFlow का इस्तेमाल करके लागू किया जाता है. चरण इस प्रकार हैं:
- कोई असली उपयोगकर्ता आपके ऐप्लिकेशन में लॉग इन करता है. आपको उस उपयोगकर्ता को ऐसे यूज़र आईडी से जोड़ना होगा जो आपके ऐप्लिकेशन के लिए यूनीक हो.
- यूज़र आईडी के आधार पर, AuthorizationCodeFlow.loadCredential(String) को कॉल करें. इससे यह पता चलता है कि उपयोगकर्ता के क्रेडेंशियल पहले से मौजूद हैं या नहीं. अगर ऐसा है, तो आपका काम हो गया है.
- अगर ऐसा नहीं है, तो AuthorizationCodeFlow.newAuthorizationUrl() को कॉल करें और असली उपयोगकर्ता के ब्राउज़र को अनुमति वाले पेज पर भेजें, जहां वह आपके ऐप्लिकेशन को अपने सुरक्षित डेटा का ऐक्सेस दे सके.
- इसके बाद, वेब ब्राउज़र एक "कोड" क्वेरी पैरामीटर के साथ दूसरे वेबलिंक पर भेजता है. इसके बाद, इसका इस्तेमाल AuthorizationCodeFlow.newTokenRequest(String) का इस्तेमाल करके ऐक्सेस टोकन का अनुरोध करने के लिए किया जा सकता है.
- सुरक्षित संसाधनों को ऐक्सेस करने के लिए क्रेडेंशियल सेव करने और उसे पाने के लिए, AuthorizationCodeFlow.createAndStoreCredential(TokenResponse, String) का इस्तेमाल करें.
इसके अलावा, अगर AuthorizationCodeFlow का इस्तेमाल नहीं किया जा रहा है, तो निचले लेवल की क्लास का इस्तेमाल किया जा सकता है:
- User-ID के आधार पर, स्टोर से क्रेडेंशियल लोड करने के लिए, DataStore.get(String) का इस्तेमाल करें.
- ब्राउज़र को ऑथराइज़ेशन पेज पर ले जाने के लिए, AuthorizationCodeRequestUrl का इस्तेमाल करें.
- ऑथराइज़ेशन रिस्पॉन्स को प्रोसेस करने और ऑथराइज़ेशन कोड को पार्स करने के लिए, AuthorizationCodeResponseUrl का इस्तेमाल करें.
- ऐक्सेस टोकन और रीफ़्रेश टोकन का अनुरोध करने के लिए AuthorizationCodeTokenRequest का इस्तेमाल करें.
- नया क्रेडेंशियल बनाएं और उसे DataStore.set(String, V) का इस्तेमाल करके सेव करें.
- क्रेडेंशियल का इस्तेमाल करके, सुरक्षित संसाधनों को ऐक्सेस करें. अगर रीफ़्रेश टोकन उपलब्ध है, तो समयसीमा खत्म हो चुके ऐक्सेस टोकन अपने-आप रीफ़्रेश हो जाते हैं. DataStoreCredentialRefreshListener का इस्तेमाल करना न भूलें. साथ ही, Credential.Builder.addRefreshListener(CredentialRefreshListener) का इस्तेमाल करके, इसे क्रेडेंशियल के लिए सेट करें.
Servlet ऑथराइज़ेशन कोड फ़्लो
इस लाइब्रेरी में, बुनियादी इस्तेमाल के उदाहरणों के लिए अनुमति कोड फ़्लो को आसान बनाने के लिए, सर्वलेट हेल्पर क्लास उपलब्ध कराई गई हैं. आपको सिर्फ़ 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 के Users Java API का फ़ायदा ले सकते हैं. Users Java API को चालू करने के लिए, उपयोगकर्ता को लॉग इन करना होगा. अगर उपयोगकर्ता पहले से लॉग इन नहीं हैं, तो उन्हें लॉगिन पेज पर रीडायरेक्ट करने के बारे में जानकारी पाने के लिए, web.xml में सुरक्षा और पुष्टि देखें.
सर्वलेट केस से मुख्य अंतर यह है कि आपने AbstractAppEngineAuthorizationCodeServlet और AbstractAppEngineAuthorizationCodeCallbackServlet (google-oauth-client-appengine से) की कंक्रीट सबक्लास दी हैं. ये एब्स्ट्रैक्ट सर्वलेट क्लास को एक्सटेंड करते हैं और Users Java API का इस्तेमाल करके, आपके लिए getUserId
तरीका लागू करते हैं. Java के लिए Google एचटीटीपी क्लाइंट लाइब्रेरी से AppEngineDataStoreFactory, Google App Engine Data Store API का इस्तेमाल करके क्रेडेंशियल को सेव करने का एक अच्छा विकल्प है.
कोड का नमूना:
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 बीयरर स्पेसिफ़िकेशन के मुताबिक, जब सर्वर को किसी ऐसे सुरक्षित संसाधन को ऐक्सेस करने के लिए कॉल किया जाता है जिसकी समयसीमा खत्म हो चुकी है, तो सर्वर आम तौर पर एक एचटीटीपी 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 को कॉल करना होगा.