Beberapa token akses Oauth2

13

Saya memiliki API yang menggunakan oAuth2 dan aplikasi seluler saya sendiri yang menggunakan API ini sebagai backend mereka. Karena pengguna dapat masuk melalui beberapa perangkat (yaitu iPhone, iPad, tablet android atau ponsel android) secara bersamaan, saya memerlukan API untuk membedakan antara setiap koneksi. Saya ingin melakukan ini melalui token akses terpisah: setiap klien mendapat token akses terpisah.

Masalahnya adalah implementasi saat ini yang kami gunakan (spring-security-oauth2) menghasilkan kunci unik berdasarkan client_id, nama pengguna, dan ruang lingkup. Jadi pada dasarnya, ketika mendapatkan token akses, semua klien mendapatkan token akses yang sama untuk pengguna yang sama. Ini dilakukan dengan menggunakan DefaultAuthenticationKeyGenerator.

Apakah aman untuk mengabaikan generator kunci otentikasi dan hanya membuat token akses baru pada setiap permintaan dari klien?

daftar periksa
sumber
2
dapatkah Anda menggunakan ruang lingkup untuk membedakan setiap klien? yaitu memberikan ios lingkup "ios", android lingkup "android", tablet lingkup "tablet", dll. Tapi FWIW saya akhirnya menulis implementasi TokenServices saya sendiri (sebenarnya saya pikir saya membuatnya menjadi pembungkus default) yang menghasilkan token baru setiap kali.
Rob
Secara umum, meskipun, implementasi Spring Security OAuth2 bekerja dengan baik untuk saya (setelah saya mendapatkan konfigurasi XML), tetapi mengelola token dan objek otentikasi adalah titik sakit yang berkelanjutan.
Rob
2
Mencari di Google untuk "DefaultAuthenticationKeyGenerator" membawa saya ke file .java di pustaka spring-security-oauth di GitHub. Kelas itu mengimplementasikan AuthenticationKeyGeneratorantarmuka. Bisakah Anda membuat implementasi Anda sendiri dan menggunakannya?
Greg Burghardt
URL ke file .java yang saya temukan: github.com/spring-projects/spring-security-oauth/blob/master/…
Greg Burghardt
2
Saya setuju dengan @Rob Anda bisa menggunakan devicetype dalam permintaan seperti "android", "ios", "web" dll
Vikash Rajpurohit

Jawaban:

1

Awan musim semi sudah menyediakan perilaku ini. Cukup tambahkan Klien yang berbeda. Seperti iosAppClient, androidAppClient di kelas AuthorizationServerConfiguration Anda.

@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")
                    ........

        }

Di backend Anda bisa mendapatkan clientID seperti berikut ini

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

dan menerapkan perilaku berbeda berdasarkan clientId.

Rocks360
sumber
0

Satu jawaban adalah bahwa setiap platform aplikasi adalah klien yang berbeda, jadi harus memiliki id klien yang berbeda. Satu untuk aplikasi iOS, satu untuk situs web, dll.

Untuk membedakan antara mengatakan iPad vs iPhone, saya sarankan untuk tidak mengandalkan sistem OAuth untuk ini.

RibaldEddie
sumber
0

Saya menemukan masalah yang sama saat mengembangkan backend saya dengan Spring Boot dan OAuth2. Masalah yang saya temui adalah, jika beberapa perangkat berbagi token yang sama, sekali satu perangkat me-refresh token, perangkat lain akan tidak mengerti dan, singkatnya, kedua perangkat dimasukkan dalam hiruk-pikuk token refresh. Solusi saya adalah mengganti default AuthenticationKeyGeneratordengan implementasi kustom yang menimpa DefaultAuthenticationKeyGeneratordan menambahkan parameter baru client_instance_iddalam campuran generator utama. Klien seluler saya kemudian akan mengirim parameter ini yang harus unik di seluruh pemasangan aplikasi (iOS atau Android). Ini bukan persyaratan khusus, karena sebagian besar aplikasi seluler sudah melacak instance aplikasi dalam beberapa bentuk.

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);
    }

}

yang kemudian akan Anda injeksi dengan cara yang sama:

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

Permintaan HTTP akan terlihat seperti ini

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}}

Manfaat menggunakan pendekatan ini adalah, jika klien tidak mengirim client_instance_id, kunci default akan dihasilkan, dan jika instance disediakan, kunci yang sama dikembalikan setiap kali untuk instance yang sama. Juga, kuncinya adalah platform independen. Kelemahannya adalah bahwa MD5 digest (digunakan secara internal) disebut dua kali.

Cosmin Radu
sumber