โทเค็นการเข้าถึง Oauth2 หลายรายการ


13

ฉันมี API ที่ใช้ oAuth2 และแอพมือถือของฉันเองที่ใช้ API นี้เป็นแบ็กเอนด์ เนื่องจากผู้ใช้สามารถเข้าสู่ระบบผ่านอุปกรณ์หลายตัว (เช่น iPhone, iPad, แท็บเล็ต Android หรือโทรศัพท์ Android) ในเวลาเดียวกันฉันจึงต้องใช้ API เพื่อแยกแยะระหว่างการเชื่อมต่อแต่ละครั้ง ฉันต้องการทำสิ่งนี้ผ่านโทเค็นการเข้าถึงแยกกัน: ลูกค้าแต่ละคนจะได้รับโทเค็นการเข้าถึงแยกต่างหาก

ปัญหาคือการใช้งานปัจจุบันที่เราใช้ (spring-security-oauth2) สร้างคีย์ที่ไม่ซ้ำกันตาม client_id ชื่อผู้ใช้และขอบเขต ดังนั้นโดยทั่วไปเมื่อได้รับโทเค็นการเข้าถึงลูกค้าทั้งหมดจะได้รับโทเค็นการเข้าถึงเดียวกันสำหรับผู้ใช้เดียวกัน สิ่งนี้ทำได้โดยใช้ DefaultAuthenticationKeyGenerator

ปลอดภัยหรือไม่หากไม่สนใจตัวสร้างคีย์การรับรองความถูกต้องและเพียงสร้างโทเค็นการเข้าถึงใหม่ในแต่ละคำขอจากลูกค้า


2
คุณสามารถใช้ขอบเขตเพื่อแยกความแตกต่างของลูกค้าแต่ละรายได้หรือไม่ ie ให้ ios ขอบเขต "ios", android และขอบเขต "android", แท็บเล็ตเป็นขอบเขต "แท็บเล็ต" ฯลฯ แต่ FWIW ฉันสิ้นสุดการเขียนการใช้ TokenServices ของตัวเอง (จริง ๆ แล้วฉันคิดว่าฉันทำให้เป็นเสื้อคลุม สร้างโทเค็นใหม่ทุกครั้ง
Rob

โดยทั่วไปแล้วการใช้งาน Spring Security OAuth2 ใช้งานได้ดีสำหรับฉัน (เมื่อฉันผ่านการกำหนดค่า XML) แต่การจัดการโทเค็นและวัตถุการตรวจสอบความถูกต้องเป็นปัญหาที่ต่อเนื่อง
Rob

2
การค้นหา Google สำหรับ "DefaultAuthenticationKeyGenerator" ทำให้ฉันไปที่ไฟล์. java ในไลบรารี spring-security-oauth บน GitHub คลาสนั้นใช้AuthenticationKeyGeneratorอินเทอร์เฟซ คุณสามารถสร้างการใช้งานของคุณเองและใช้สิ่งนั้นแทนได้หรือไม่?
Greg Burghardt

พบ URL ไปยังไฟล์. java ที่พบ: github.com/spring-projects/spring-security-oauth/blob/master/…
Greg Burghardt

2
ฉันเห็นด้วยกับ @Rob คุณสามารถไปกับ devicetype ตามที่ขอเช่น "android", "ios", "web" ฯลฯ
Vikash Rajpurohit

คำตอบ:


1

Spring cloud แสดงพฤติกรรมนี้แล้ว เพียงเพิ่มลูกค้าอื่น เช่น iosAppClient, androidAppClient ในคลาส AuthorizationServerConfiguration ของคุณ

@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

ฉันพบปัญหาเดียวกันขณะพัฒนาแบ็กเอนด์ด้วย Spring Boot และ 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คีย์เริ่มต้นจะถูกสร้างขึ้นและหากมีการให้อินสแตนซ์คีย์เดียวกันจะถูกส่งกลับทุกครั้งสำหรับอินสแตนซ์เดียวกัน นอกจากนี้ที่สำคัญคือแพลตฟอร์มอิสระ ข้อเสียก็คือการแยกย่อย MD5 (ใช้ภายใน) เรียกว่าสองครั้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.