多个Oauth2访问令牌


13

我有一个使用oAuth2的API和我自己的使用此API作为后端的移动应用。由于用户可以同时通过多个设备(例如iPhone,iPad,Android平板电脑或Android手机)登录,因此我需要API来区分每个连接。我想通过单独的访问令牌来执行此操作:每个客户端都获得一个单独的访问令牌。

问题是我们使用的当前实现(spring-security-oauth2)基于client_id,用户名和范围生成唯一的密钥。因此,基本上,当获得访问令牌时,所有客户端都会为同一用户获得相同的访问令牌。这是使用DefaultAuthenticationKeyGenerator完成的。

忽略身份验证密钥生成器并仅在来自客户端的每个请求上简单地创建一个新的访问令牌是否安全?


2
您可以利用范围来区分每个客户吗?例如,给ios一个“ ios”范围,给一个android一个“ android”范围,给平板电脑一个“ tablet”范围,等等。但是FWIW我最终写了我自己的TokenServices实现(实际上,我认为我使它成为默认值的包装器),每次都会生成一个全新的令牌。
罗布

虽然总的来说,Spring Security OAuth2实现对我来说效果很好(一旦我通过XML配置),但是管理令牌和认证对象是一个持续的难题。
罗布

2
在Google上搜索“ DefaultAuthenticationKeyGenerator”会导致我在GitHub的spring-security-oauth库中找到一个.java文件。该类实现AuthenticationKeyGenerator接口。您可以创建自己的实现并使用它吗?
格雷格·伯格哈特


2
我同意@Rob,您可以在请求中使用设备类型,例如“ android”,“ ios”,“ web”等
Vikash Rajpurohit

Answers:


1

Spring Cloud已经提供了这种行为。只需添加其他客户即可。与iosAppAppClient一样,您的AuthorizationServerConfiguration类中的androidAppClient。

@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

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

并根据clientId实现不同的行为。


0

一个答案是,每个应用程序平台都是不同的客户端,因此应具有不同的客户端ID。一个用于iOS应用程序,一个用于网站等。

至于说iPad和iPhone之间的区别,我建议不要依靠OAuth系统。


0

在使用Spring Boot和OAuth2开发后端时,我偶然发现了相同的问题。我遇到的问题是,如果多个设备共享相同的令牌,则一台设备刷新令牌后,另一台设备将变得毫无头绪,长话短说,两台设备都进入了令牌刷新狂潮。我的解决方案是AuthenticationKeyGenerator用自定义实现替换默认值,该实现DefaultAuthenticationKeyGeneratorclient_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摘要(内部使用)被调用了两次。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.