我已将身份服务器3配置为项目的IdP,我们有3个客户端:MVC web,IOS和Android。 使用混合流程,MVC应用程序的一切都很好。
对于IOS和Android,使用本机oidc客户端(AppAuth IOS和AppAuth 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客户端并没有要求客户端共享密钥,所以流量因此而被破坏。
答案 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