对身份服务器

时间:2017-02-01 06:27:28

标签: android ios identityserver3 appauth

我已将身份服务器3配置为项目的IdP,我们有3个客户端:MVC web,IOS和Android。 使用混合流程,MVC应用程序的一切都很好。

对于IOS和Android,使用本机oidc客户端(AppAuth IOSAppAuth android)无效,即使我将流配置为与PKCE混合使用。

现在当我尝试使用Xamarin在Android上创建POC,并使用IdentityModel.oidcClient时,一切都按预期工作,获取访问权限,刷新和id令牌。 当使用AppAuth for IOS和android时,我收到以下错误:

{"type":0,"code":9,"errorDescription":"Response state param did not match request state"}

知道缺少什么吗?

我怀疑那两个本地oidc客户端并没有要求客户端共享密钥,所以流量因此而被破坏。

2 个答案:

答案 0 :(得分:0)

对于AppAuth-Android here上的混合流支持,我们有一个未解决的问题。这个问题的主要问题是混合流不适合移动应用程序,因为每次访问令牌到期时都需要通过SafariViewController / CustomTab重复触发Web流。获取刷新令牌以允许后台更新访问令牌对于本机应用程序更好。

由于IdentityServer3是经过认证的OpenID Connect实施,您应该能够使用授权代码流来获取刷新令牌。

答案 1 :(得分:-1)

移动应用程序和Identity Server中的数据应该相同,

在服务器上:

new Client
        {
            ClientId = "myClientId",
            ClientName = "myClientName",
            AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
            RequireConsent = false,

            ClientSecrets =
            {
                new Secret("myClientSecret".Sha256())
            },

            RedirectUris = { "myRedirectUri://callback" },

            AllowedScopes =
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                IdentityServerConstants.StandardScopes.Phone,
            },

            AllowOfflineAccess = true
        }

点击登录android:

    AuthManager authManager = AuthManager.getInstance(this);
    AuthorizationService authService = authManager.getAuthService();
    Auth auth = authManager.getAuth();

    AuthorizationRequest authRequest = new AuthorizationRequest
        .Builder(
        authManager.getAuthConfig(),
        auth.getClientId(),
        auth.getResponseType(),
        Uri.parse(auth.getRedirectUri()))
        .setScope(auth.getScope())
        .build();

    Intent authIntent = new Intent(this, LoginAuthActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, authRequest.hashCode(), authIntent, 0);

    authService.performAuthorizationRequest(
        authRequest,
        pendingIntent);

要求代币:

    final AuthorizationResponse resp = AuthorizationResponse.fromIntent(getIntent());
    AuthorizationException ex = AuthorizationException.fromIntent(getIntent());

    final AuthManager authManager = AuthManager.getInstance(this);
    authManager.setAuthState(resp,ex);

    if (resp != null) {

        ClientSecretPost clientSecretPost = new ClientSecretPost(authManager.getAuth().getClientSecret());
        TokenRequest tokenRequest = new TokenRequest
            .Builder(authManager.getAuthConfig(), authManager.getAuth().getClientId())
            .setAuthorizationCode(resp.authorizationCode)
            .setRedirectUri(Uri.parse(authManager.getAuth().getRedirectUri()))
            .build();

        mAuthService = authManager.getAuthService();

        mAuthService.performTokenRequest(tokenRequest, clientSecretPost, new AuthorizationService.TokenResponseCallback() {
            @Override public void onTokenRequestCompleted(@Nullable TokenResponse response, @Nullable AuthorizationException ex) {
                if(ex == null) {
                    authManager.updateAuthState(response,ex);
                    MyApp.Token = authManager.getAuthState().getIdToken();
                    startService(new Intent(LoginAuthActivity.this, TokenService.class));
                    Intent mainIntent = new Intent(LoginAuthActivity.this, MainActivity.class);
                    startActivity(mainIntent);
                    finish();
                }
                else{
                    Intent loginIntent = new Intent(LoginAuthActivity.this, LoginActivity.class);
                    startActivity(loginIntent);
                    finish();
                }
            }
        });

        // authorization completed
    } else {
        // authorization failed, check ex for more details
        Intent loginIntent = new Intent(LoginAuthActivity.this, LoginActivity.class);
        startActivity(loginIntent);
        finish();
    }

AuthManager类:

public class AuthManager {
private static AuthManager instance;
private AuthState mAuthState;
private Auth mAuth;
private AuthorizationServiceConfiguration mAuthConfig;
private SharedPreferencesRepository mSharedPrefRep;
private AuthorizationService mAuthService;

public static AuthManager getInstance(Context context) {
    if (instance == null) {
        instance = new AuthManager(context);
    }
    return instance;
}

private AuthManager(Context context){
    mSharedPrefRep = new SharedPreferencesRepository(context);
    setAuthData();
    mAuthConfig = new AuthorizationServiceConfiguration(
            Uri.parse(mAuth.getAuthorizationEndpointUri()),
            Uri.parse(mAuth.getTokenEndpointUri()),
            null);
    mAuthState = mSharedPrefRep.getAuthState();

    mAuthService = new AuthorizationService(context);
}



public AuthorizationServiceConfiguration getAuthConfig() {
    return mAuthConfig;
}

public Auth getAuth() {
    if(mAuth == null){
       setAuthData();
    }

    return mAuth;
}

public AuthState getAuthState(){
    return mAuthState;
}

public void updateAuthState(TokenResponse response, AuthorizationException ex){
    mAuthState.update(response,ex);
    mSharedPrefRep.saveAuthState(mAuthState);
}

public void setAuthState(AuthorizationResponse response, AuthorizationException ex){
    if(mAuthState == null)
        mAuthState = new AuthState(response,ex);

    mSharedPrefRep.saveAuthState(mAuthState);
}

public AuthorizationService getAuthService(){
    return mAuthService;
}

private void setAuthData(){
    mAuth = new Auth();
    mAuth.setClientId(BuildConfig.CLIENT_ID);
    mAuth.setAuthorizationEndpointUri(BuildConfig.AUTHORIZSTION_END_POINT_URI);
    mAuth.setClientSecret(BuildConfig.CLIENT_SECRET);
    mAuth.setRedirectUri(BuildConfig.REDIRECT_URI);
    mAuth.setScope(BuildConfig.SCOPE);
    mAuth.setTokenEndpointUri(BuildConfig.TOKEN_END_POINT_URI);
    mAuth.setResponseType(BuildConfig.RESPONSE_TYPE);
}
}

此处的服务将要求刷新令牌。

我使用带有AppAuth-Android的Identity Server 4制作了一个示例,您可以查看它here