6

Przykład na AspNet.Security.OpenIdConnect.Server wygląda na mnie jak serwer uwierzytelniania i serwer zasobów. Chciałbym je rozdzielić. Tak zrobiłem.Oddzielanie serwerów uwierzytelniania i zasobów za pomocą AspNet.Security.OpenIdConnect - odbiorców?

Na Startup.Config serwer uwierzytelniający jest, mam następujące ustawienia:

app.UseOpenIdConnectServer(options => { 

    options.AllowInsecureHttp = true; 
    options.ApplicationCanDisplayErrors = true; 
    options.AuthenticationScheme = OpenIdConnectDefaults.AuthenticationScheme; 
    options.Issuer = new System.Uri("http://localhost:61854"); // This auth server 
    options.Provider = new AuthorizationProvider(); 
    options.TokenEndpointPath = new PathString("/token");    
    options.UseCertificate(new X509Certificate2(env.ApplicationBasePath + "\\mycertificate.pfx","mycertificate")); 

}); 

Mam AuthorizationProvider napisane, ale nie sądzę, że to istotne dla mojego obecnego problemu (ale być może istotne). Na GrantResourceOwnerCredentials ręcznym, ja ciężko kod główny roszczeń tak, że sprawdza za każdym tokena życzenie:

public override Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsNotification context) 
{ 
    var identity = new ClaimsIdentity(OpenIdConnectDefaults.AuthenticationScheme); 

    identity.AddClaim(ClaimTypes.Name, "me"); 
    identity.AddClaim(ClaimTypes.Email, "[email protected]"); 
    var claimsPrincipal = new ClaimsPrincipal(identity); 

    context.Validated(claimsPrincipal); 
    return Task.FromResult<object>(null); 
} 

na serwerze zasobów, mam następujący w Startup.config:

app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch => 
{ 
    branch.UseOAuthBearerAuthentication(options => { 
     options.Audience = "http://localhost:54408"; // This resource server, I believe. 
     options.Authority = "http://localhost:61854"; // The auth server 
     options.AutomaticAuthentication = true;    
    }); 
}); 

na Skrzypek, poprosić o dowód, a ja dostać jeden:

POST /token HTTP/1.1 
Host: localhost:61854 
Content-Type: application/x-www-form-urlencoded 

username=admin&password=aaa000&grant_type=password 

Więc teraz używam tego token dostępu, aby uzyskać dostęp do chronionego zasobu z serwera zasobów:

GET /api/values HTTP/1.1 
Host: localhost:54408 
Content-Type: application/json;charset=utf-8 
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI..... 

Teraz pojawia się ten błąd - weryfikacja odbiorców nie powiodła się. Odbiorcy: "puste". Nie pasuje do validationParameters.ValidAudience: 'http://localhost:54408' lub validationParameters.ValidAudiences: 'null'.

Myślę, że powodem jest fakt, że nigdy nie ustawiłem widowni na serwerze auth (przy app.UseOpenIdConnectServer (...)), więc nie sądzę, że zapisał informacje o odbiorcach do tokena. Dlatego muszę ustawić grupę docelową na serwerze auth (tak jak dzieje się to w IdentityServer3), ale nie mogę znaleźć właściwości w obiekcie opcji, który pozwoliłby mi to zrobić.

Czy narzędzie AspNet.Security.OpenIdConnect.Server wymaga, aby uwierzytelnienie i zasób znajdowały się na tym samym serwerze?

Czy publiczność jest przygotowywana podczas składania oświadczeń składających roszczenia, a jeśli tak, to w jaki sposób?

Czy muszę napisać niestandardowy weryfikator odbiorców i podłączyć go do systemu? (Mam nadzieję, że odpowiedź na to pytanie brzmi: nie.)

Odpowiedz

5

Czy narzędzie AspNet.Security.OpenIdConnect.Server wymaga, aby uwierzytelnienie i zasób znajdowały się na tym samym serwerze?

Nie, można oczywiście oddzielić dwie role.

Jak już ustaliłeś, jeśli nie określisz go jawnie, serwer autoryzacji nie ma możliwości określenia miejsca docelowego/grupy odbiorców tokenu dostępu, który jest wydany bez żądania aud wymaganego domyślnie przez O oprogramowaniu użytkowym OAuth2.

Rozwiązanie tego problemu jest proste: wystarczy zadzwonić ticket.SetResources(resources) podczas tworzenia bilet uwierzytelniania i autoryzacji serwer będzie wiedział dokładnie, jakie wartości (S) (tj serwerów zasobów/API) Należy dodać w aud zastrzeżeniu (ach).

app.UseOpenIdConnectServer(options => 
{ 
    // Force the OpenID Connect server middleware to use JWT tokens 
    // instead of the default opaque/encrypted token format used by default. 
    options.AccessTokenHandler = new JwtSecurityTokenHandler(); 
}); 

public override Task HandleTokenRequest(HandleTokenRequestContext context) 
{ 
    if (context.Request.IsPasswordGrantType()) 
    { 
     var identity = new ClaimsIdentity(context.Options.AuthenticationScheme); 
     identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "unique identifier"); 

     var ticket = new AuthenticationTicket(
      new ClaimsPrincipal(identity), 
      new AuthenticationProperties(), 
      context.Options.AuthenticationScheme); 

     // Call SetResources with the list of resource servers 
     // the access token should be issued for. 
     ticket.SetResources("resource_server_1"); 

     // Call SetScopes with the list of scopes you want to grant. 
     ticket.SetScopes("profile", "offline_access"); 

     context.Validate(ticket); 
    } 

    return Task.FromResult(0); 
}  

app.UseJwtBearerAuthentication(new JwtBearerOptions 
{ 
    AutomaticAuthenticate = true, 
    AutomaticChallenge = true, 
    Audience = "resource_server_1", 
    Authority = "http://localhost:61854" 
}); 
+0

Dziękuję bardzo! Teraz działa! Użyłem opcji 1, ponieważ może mieć więcej niż jeden odbiorca z prośbą o dostęp do tokenów dostępu. –

+0

@MickaelCaruso Zaktualizowałem swoją odpowiedź, aby użyć 'ticket.SetResources' jako parametru' resource' nie będzie już obsługiwany natywnie w następnej wersji beta (zobacz https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect. Serwer/issues/186, aby uzyskać więcej informacji). Przestaniemy też używać JWT jako domyślnego formatu tokenów dostępu: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/issues/186 – Pinpoint

+0

Dziękuję za odpowiedź, to naprawdę mi pomogło. Moja metoda GrantResourceOwnerCredentials jest prawie taka sama, ale dodałem także identity.AddClaim (ClaimTypes.Name, "MyFullName"); Ale kiedy zadzwonię do User.GetUserName() w moim kontrolerze web api otrzymuję NULL? User.GetUserId() zwraca to, co jest przekazywane w roszczeniu NameIdentifier. Jak mogę uzyskać User.GetUserName do zwrócenia danych? – partyelite

Powiązane problemy