एकाधिक Oauth2 पहुंच टोकन


13

मेरे पास एक API है जो oAuth2 और मेरे अपने मोबाइल ऐप का उपयोग करता है जो इस API का उपयोग अपने बैकएंड के रूप में करते हैं। चूंकि उपयोगकर्ताओं को एक ही समय में कई उपकरणों (यानी आईफोन, आईपैड, एंड्रॉइड टैबलेट या एंड्रॉइड फोन) के माध्यम से लॉग इन किया जा सकता है, मुझे प्रत्येक कनेक्शन के बीच अंतर करने के लिए एपीआई की आवश्यकता होती है। मैं इसे अलग-अलग एक्सेस टोकन के माध्यम से करना चाहता हूं: प्रत्येक क्लाइंट को एक अलग एक्सेस टोकन मिलता है।

समस्या यह है कि वर्तमान कार्यान्वयन जिसे हम उपयोग करते हैं (वसंत-सुरक्षा-oauth2) क्लाइंट_आईडी, उपयोगकर्ता नाम और कार्यक्षेत्र के आधार पर एक अद्वितीय कुंजी उत्पन्न करता है। इसलिए मूल रूप से, एक्सेस टोकन प्राप्त करते समय, सभी क्लाइंट को समान उपयोगकर्ता के लिए समान एक्सेस टोकन मिलता है। यह DefaultAuthenticationKeyGenerator का उपयोग करके किया जाता है।

क्या प्रमाणीकरण कुंजी जनरेटर को अनदेखा करना और ग्राहक से प्रत्येक अनुरोध पर बस एक नया एक्सेस टोकन बनाना सुरक्षित है?


2
क्या आप प्रत्येक ग्राहक को अलग करने के लिए गुंजाइश का उपयोग कर सकते हैं? यानी ios को "ios" स्कोप दें, एंड्रॉइड को "एंड्रॉइड" स्कोप, टैबलेट को "टैब्लेट" स्कोप, इत्यादि दें, लेकिन FWIW मैंने अपना खुद का टोकनसेन्समेंट लिखना शुरू कर दिया (वास्तव में मुझे लगता है कि मैंने इसे डिफ़ॉल्ट के आसपास एक रैपर बनाया है) हर बार एक नया टोकन बनाया।
रोब

सामान्य तौर पर, हालांकि, स्प्रिंग सिक्योरिटी OAuth2 कार्यान्वयन ने मेरे लिए अच्छा काम किया (एक बार मुझे एक्सएमएल कॉन्फ़िगरेशन के माध्यम से मिला), लेकिन टोकन और ऑथेंटिकेशन ऑब्जेक्ट्स का प्रबंधन एक निरंतर दर्द बिंदु था।
राब

2
"DefaultAuthenticationKeyGenerator" के लिए Google पर खोज करने से मुझे GitHub पर वसंत-सुरक्षा-ऑउथ लाइब्रेरी में एक .java फ़ाइल में ले जाया गया। वह वर्ग AuthenticationKeyGeneratorइंटरफ़ेस को लागू करता है। क्या आप अपना स्वयं का कार्यान्वयन बना सकते हैं और इसके बजाय उसका उपयोग कर सकते हैं?
ग्रेग बरगार्ड

URL .java फ़ाइल में मैंने पाया: github.com/spring-projects/spring-security-oauth/blob/master/…
ग्रेग बरहार्ट

2
मैं इस बात से सहमत हूं कि @Rob में आप "android", "ios", "web" इत्यादि जैसे अनुरोधों के साथ जा सकते हैं
Vikash Rajpurohit

जवाबों:


1

स्प्रिंग क्लाउड पहले से ही यह व्यवहार प्रदान करता है। बस अलग-अलग ग्राहक जोड़ें। IosAppClient की तरह, अपने प्राधिकरण में AndroidAppClientServerConfiguration क्लास।

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
                clients.inMemory().withClient("androidAppclient")
                    .secret("clientsecret")
                    .autoApprove(true)
                    .accessTokenValiditySeconds(120)
                    .authorizedGrantTypes("password")
                    .resourceIds("accountservice")
                    .scopes("read", "write")
                    .and()
                    .withClient("iosappclient")
                    ........

        }

बैकएंड में आप निम्नलिखित की तरह क्लाइंटआईडी प्राप्त कर सकते हैं

clientId = ((OAuth2Authentication) authentication).getOAuth2Request().getClientId();

और clientId के आधार पर अलग व्यवहार लागू करें।


0

एक उत्तर यह है कि प्रत्येक ऐप प्लेटफ़ॉर्म एक अलग क्लाइंट है, इसलिए एक अलग क्लाइंट आईडी होना चाहिए। IOS ऐप के लिए एक, वेब साइट के लिए एक, आदि।

जैसा कि iPad बनाम iPhone के बीच अंतर करने के लिए, मैं इसके लिए OAuth सिस्टम पर भरोसा नहीं करने का सुझाव दूंगा।


0

मैं स्प्रिंग बूट और OAuth2 के साथ अपने बैकेंड को विकसित करते समय एक ही समस्या पर ठोकर खाई। मेरे सामने जो समस्या थी, वह यह थी कि, यदि कई उपकरणों ने एक ही टोकन साझा किया, तो एक बार एक टोकन को रीफ्रेश करने के बाद, दूसरा डिवाइस क्लूलेस होगा और लंबी कहानी छोटी होगी, दोनों डिवाइस एक टोकन रिफ्रेश उन्माद में प्रवेश करते हैं। मेरा समाधान AuthenticationKeyGeneratorएक कस्टम कार्यान्वयन के साथ डिफ़ॉल्ट को बदलना था जो कुंजी जनरेटर मिश्रण में ओवरराइड करता है DefaultAuthenticationKeyGeneratorऔर एक नया पैरामीटर जोड़ता है client_instance_id। मेरे मोबाइल क्लाइंट तब इस पैरामीटर को भेजते हैं, जिसे ऐप इंस्टॉल (iOS या Android) में अद्वितीय होना चाहिए। यह एक विशेष आवश्यकता नहीं है, क्योंकि अधिकांश मोबाइल एप्लिकेशन पहले से ही किसी न किसी रूप में एप्लिकेशन इंस्टेंस को ट्रैक करते हैं।

public class EnhancedAuthenticationKeyGenerator extends DefaultAuthenticationKeyGenerator {

    public static final String PARAM_CLIENT_INSTANCE_ID = "client_instance_id";

    private static final String KEY_SUPER_KEY = "super_key";
    private static final String KEY_CLIENT_INSTANCE_ID = PARAM_CLIENT_INSTANCE_ID;

    @Override
    public String extractKey(final OAuth2Authentication authentication) {
        final String superKey = super.extractKey(authentication);

        final OAuth2Request authorizationRequest = authentication.getOAuth2Request();
        final Map<String, String> requestParameters = authorizationRequest.getRequestParameters();

        final String clientInstanceId = requestParameters != null ? requestParameters.get(PARAM_CLIENT_INSTANCE_ID) : null;
        if (clientInstanceId == null || clientInstanceId.length() == 0) {
            return superKey;
        }

        final Map<String, String> values = new LinkedHashMap<>(2);
        values.put(KEY_SUPER_KEY, superKey);
        values.put(KEY_CLIENT_INSTANCE_ID, clientInstanceId);

        return generateKey(values);
    }

}

जिसके बाद आप एक समान तरीके से इंजेक्ट करेंगे:

final JdbcTokenStore tokenStore = new JdbcTokenStore(mDataSource);
tokenStore.setAuthenticationKeyGenerator(new EnhancedAuthenticationKeyGenerator());

HTTP अनुरोध फिर कुछ इस तरह दिखेगा

POST /oauth/token HTTP/1.1
Host: {{host}}
Authorization: Basic {{auth_client_basic}}
Content-Type: application/x-www-form-urlencoded

grant_type=password&username={{username}}&password={{password}}&client_instance_id={{instance_id}}

इस दृष्टिकोण का उपयोग करने का लाभ यह है कि, यदि ग्राहक ए नहीं भेजता है client_instance_id, तो डिफ़ॉल्ट कुंजी उत्पन्न होगी, और यदि कोई उदाहरण प्रदान किया जाता है, तो उसी कुंजी को हर बार उसी उदाहरण के लिए लौटाया जाता है। इसके अलावा, कुंजी प्लेटफ़ॉर्म स्वतंत्र है। नकारात्मक पक्ष यह होगा कि एमडी 5 डाइजेस्ट (आंतरिक रूप से प्रयुक्त) को दो बार कहा जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.