2017-02-01 20 views
0

IDC 3을 프로젝트의 IdP로 구성했습니다. MVC 웹, IOS 및 Android의 세 가지 클라이언트가 있습니다. Hybrid 흐름을 사용하여 모든 것이 MVC 앱에 적합합니다.AppAuth oidc ID 서버 인증시 유효하지 않은 상태 오류

IOS 및 Android의 경우, 원시 oidc 클라이언트 (AppAuth IOSAppAuth android)를 사용하여 흐름을 PKCE와 하이브리드로 구성 했더라도 작동하지 않습니다.

이제 Xamarin을 사용하여 Android에서 POC를 만들고 IdentityModel.oidcClient를 사용하여 모든 것이 예상대로 작동하여 액세스, 새로 고침 및 ID 토큰을 얻습니다. IOS에 대한 AppAuth을 사용하고 안드로이드 나는 다음과 같은 오류가 무엇입니까 때

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

무슨 일이없는 어떤 생각을?

나는 두 개의 고유 한 클라이언트가 클라이언트의 공유 비밀을 요구하지 않으므로 그 때문에 흐름이 손상되었다고 생각합니다.

+0

을 확인할 수 있습니다 이것을 OIDC 라이브러리가 쿼리 문자열을 기대하면서 인증 응답이 리디렉션 URI에 조각으로 반환되기 때문이다 이에 대한 응답으로 도서관은 응답을 얻는 데 성공하지 못했습니다. 라이브러리가 스펙을 따르지 않고 있지만 실제로 두 라이브러리가 하이브리드 플로우를 지원한다고 의심하고 있습니다. 해당 라이브러리는 Google IdP 사례를 처리하며 이는 구현 자용입니다. –

+0

도서관은 Google과 관련이 없습니다. 이들은 기본 앱용 OAuth2의 권장 사항을 구현합니다. https://tools.ietf.org/html/draft-ietf-oauth-native-apps-07 – iainmcgin

답변

0

우리는 AppAuth-Android here에서 하이브리드 흐름 지원에 대한 미해결 문제가 있습니다. 주요 문제는 액세스 토큰이 만료 될 때마다 SafariViewController/CustomTab을 통해 웹 플로우를 반복적으로 트리거해야하므로 하이브리드 플로우가 모바일 애플리케이션에 적합하지 않다는 것입니다. 액세스 토큰의 배경 업데이트를 허용하는 새로 고침 토큰을 얻는 것이 네이티브 앱에 더 좋습니다.

IdentityServer3는 인증 된 OpenID Connect 구현이므로 인증 코드 플로우를 사용하여 새로 고침 토큰을 얻을 수 있어야합니다.

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 
     } 

클릭 로그인에 안드로이드에서 :

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

요청

-1

데이터는 서버에

, 모바일 앱과는 Identity Server에서 동일해야합니다 토큰 :

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(); 
    } 
(210 개)

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 - 안드로이드 신원 서버 (4)를 사용하여 샘플을 만들었습니다 당신이 그것을 here

+1

이 링크가 질문에 대답 할 수 있지만 필수 부분을 포함하는 것이 좋습니다 여기에 답을 입력하고 참조 용 링크를 제공하십시오. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않게 될 수 있습니다.- [검토 중] (리뷰/저품절 게시물/16649743) – Alberto

+0

나는 대답을 편집 – Hadi