Authentifizierung und Autorisierung
Hinweis
Dieses eBook wurde im Frühjahr 2017 veröffentlicht und wurde seitdem nicht aktualisiert. Es gibt viel in dem Buch, das wertvoll bleibt, aber einige der Materialien sind veraltet.
Die Authentifizierung ist der Prozess des Abrufens von Identifikationsanmeldeinformationen wie Name und Kennwort von einem Benutzer und das Überprüfen dieser Anmeldeinformationen für eine Autorität. Wenn die Anmeldeinformationen gültig sind, wird die Entität, die die Anmeldeinformationen übermittelt hat, als authentifizierte Identität betrachtet. Nachdem eine Identität authentifiziert wurde, bestimmt ein Autorisierungsprozess, ob diese Identität Zugriff auf eine bestimmte Ressource hat.
Es gibt viele Ansätze zur Integration von Authentifizierung und Autorisierung in eine Xamarin.Forms App, die mit einer ASP.NET MVC-Webanwendung kommuniziert, einschließlich der Verwendung von ASP.NET Core Identity, externen Authentifizierungsanbietern wie Microsoft, Google, Facebook oder Twitter und Authentifizierungs-Middleware. Die mobile eShopOnContainers-App führt Authentifizierung und Autorisierung mit einem containerisierten Identitäts-Microservice durch, der IdentityServer 4 verwendet. Die mobile App fordert Sicherheitstoken von IdentityServer an, entweder für die Authentifizierung eines Benutzers oder für den Zugriff auf eine Ressource. Damit IdentityServer Token im Namen eines Benutzers ausstellen kann, muss sich der Benutzer bei IdentityServer anmelden. IdentityServer hat jedoch keine Benutzeroberfläche oder Datenbank für die Authentifizierung. Daher wird in der Referenzanwendung „eShopOnContainers“ ASP.NET Core Identity für diesen Zweck verwendet.
Authentifizierung
Die Authentifizierung ist erforderlich, wenn eine Anwendung die Identität des aktuellen Benutzers kennen muss. Der primäre Mechanismus von ASP.NET Core zum Identifizieren von Benutzer*innen ist das Mitgliedschaftssystem „ASP.NET Core Identity“, das Benutzerinformationen in einem von dem oder der Entwickler*in konfigurierten Datenspeicher speichert. In der Regel handelt es sich bei diesem Datenspeicher um einen EntityFramework-Speicher, obwohl benutzerdefinierte Speicher oder Pakete von Drittanbietern verwendet werden können, um Identitätsinformationen in Azure Storage, Azure Cosmos DB oder anderen Speicherorten zu speichern.
Für Authentifizierungsszenarien, die einen lokalen Benutzerdatenspeicher verwenden und Identitätsinformationen zwischen Anforderungen über Cookies beibehalten (wie in ASP.NET MVC-Webanwendungen üblich), ist ASP.NET Core Identity eine geeignete Lösung. Cookies sind jedoch nicht immer das übliche Mittel zum Speichern und Übertragen von Daten. Eine ASP.NET Core-Webanwendung, die RESTful-Endpunkte verfügbar macht, auf die über eine mobile App zugegriffen wird, muss in der Regel die Bearertokenauthentifizierung verwenden, da Cookies in diesem Szenario nicht verwendet werden können. Bearertoken können jedoch problemlos abgerufen und in den Autorisierungsheader von Webanforderungen aufgenommen werden, die von der mobilen App vorgenommen wurden.
Ausstellen von Bearertoken mit IdentityServer 4
IdentityServer 4 ist ein Open Source OpenID Connect- und OAuth 2.0-Framework für ASP.NET Core, das für viele Authentifizierungs- und Autorisierungsszenarien verwendet werden kann, einschließlich des Ausstellens von Sicherheitstoken für lokale ASP.NET Core Identity-Benutzer.
Hinweis
OpenID Connect und OAuth 2.0 sind sehr ähnlich, haben jedoch unterschiedliche Zuständigkeiten.
OpenID Connect ist eine Authentifizierungsschicht, die auf dem OAuth 2.0-Protokoll aufbaut. OAuth 2 ist ein Protokoll, mit dem Anwendungen Zugriffstoken von einem Sicherheitstokendienst anfordern und für die Kommunikation mit APIs verwenden können. Diese Delegierung reduziert die Komplexität sowohl in Clientanwendungen als auch in APIs, da Authentifizierung und Autorisierung zentralisiert werden können.
Die Kombination aus OpenID Connect und OAuth 2.0 kombiniert die beiden grundlegenden Sicherheitsaspekte der Authentifizierung und des API-Zugriffs, und IdentityServer 4 ist eine Implementierung dieser Protokolle.
In Anwendungen, die eine direkte Client-zu-Microservice-Kommunikation verwenden, z. B. die eShopOnContainers-Referenzanwendung, kann ein dedizierter Authentifizierungs-Microservice verwendet werden, der als Sicherheitstokendienst (Security Token Service, STS) fungiert, wie in Abbildung 9-1 dargestellt. Weitere Informationen zur direkten Client-zu-Microservice-Kommunikation finden Sie unter Communication Between Client and Microservices.
Abbildung 9-1: Authentifizierung durch einen dedizierten Authentifizierungs-Microservice
Die mobile eShopOnContainers-App kommuniziert mit dem Identitäts-Microservice, der IdentityServer 4 zum Durchführen der Authentifizierung und Zugriffssteuerung für APIs verwendet. Daher fordert die mobile App Token von IdentityServer an, entweder für die Authentifizierung eines Benutzers oder für den Zugriff auf eine Ressource:
- Die Authentifizierung von Benutzern mit IdentityServer wird durch die mobile App erreicht, die ein Identitätstoken anfordert, das das Ergebnis eines Authentifizierungsprozesses darstellt. Es enthält mindestens einen Bezeichner für den Benutzer und Informationen dazu, wie und wann der Benutzer authentifiziert wurde. Sie kann auch zusätzliche Identitätsdaten enthalten.
- Der Zugriff auf eine Ressource mit IdentityServer wird durch die mobile App erreicht, die ein Zugriffstoken anfordert, das den Zugriff auf eine API-Ressource ermöglicht. Clients fordern Zugriffstoken an und leiten sie an die API weiter. Zugriffstoken enthalten Informationen über den Client und den Benutzer (sofern vorhanden). APIs verwenden diese Informationen dann, um den Zugriff auf ihre Daten zu autorisieren.
Hinweis
Ein Client muss mit IdentityServer registriert werden, bevor er Token anfordern kann.
Hinzufügen von IdentityServer zu einer Webanwendung
Damit eine ASP.NET Core-Webanwendung IdentityServer 4 verwenden kann, muss sie der Visual Studio-Projektmappe der Webanwendung hinzugefügt werden. Weitere Informationen finden Sie in der IdentityServer-Dokumentation im Überblick .
Sobald IdentityServer in der Visual Studio-Lösung der Webanwendung enthalten ist, muss sie der HTTP-Anforderungsverarbeitungspipeline der Webanwendung hinzugefügt werden, damit sie Anforderungen an OpenID Connect- und OAuth 2.0-Endpunkte bereitstellen kann. Verwenden Sie hierfür wie im folgenden Codebeispiel veranschaulicht die Configure
-Methode in der Startup
-Klasse der Webanwendung:
public void Configure(
IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseIdentity();
...
}
Die Reihenfolge ist in der HTTP-Anforderungsverarbeitungspipeline der Webanwendung wichtig. Aus diesem Grund muss IdentityServer der Pipeline vor dem Benutzeroberflächenframework hinzugefügt werden, das den Anmeldebildschirm implementiert.
Konfigurieren von IdentityServer
IdentityServer sollte in der Methode in der ConfigureServices
Klasse der Webanwendung Startup
durch Aufrufen der services.AddIdentityServer
Methode konfiguriert werden, wie im folgenden Codebeispiel aus der eShopOnContainers-Referenzanwendung veranschaulicht:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddIdentityServer(x => x.IssuerUri = "null")
.AddSigningCredential(Certificate.Get())
.AddAspNetIdentity<ApplicationUser>()
.AddConfigurationStore(builder =>
builder.UseSqlServer(connectionString, options =>
options.MigrationsAssembly(migrationsAssembly)))
.AddOperationalStore(builder =>
builder.UseSqlServer(connectionString, options =>
options.MigrationsAssembly(migrationsAssembly)))
.Services.AddTransient<IProfileService, ProfileService>();
}
Nach dem Aufrufen der services.AddIdentityServer
-Methode werden zusätzliche Fluent-APIs aufgerufen, um Folgendes zu konfigurieren:
- Die Anmeldeinformationen, die zum Signieren verwendet werden
- Die API- und Identitätsressourcen, auf die Benutzer*innen möglicherweise Zugriff anfordern
- Die Clients, die eine Verbindung herstellen, um Token anzufordern
- ASP.NET Core Identity
Tipp
Laden Sie die IdentityServer 4-Konfiguration dynamisch. Die APIs von IdentityServer 4 ermöglichen das Konfigurieren von IdentityServer über eine In-Memory-Liste mit Konfigurationsobjekten. In der Referenzanwendung „eShopOnContainers“ werden diese In-Memory-Sammlungen in die Anwendung hartcodiert. In Produktionsszenarios können sie jedoch dynamisch aus einer Konfigurationsdatei oder aus einer Datenbank geladen werden.
Weitere Informationen zum Konfigurieren von IdentityServer für die Verwendung von ASP.NET Core Identity finden Sie unter Verwenden von ASP.NET Core Identity in der IdentityServer-Dokumentation.
Konfigurieren von API-Ressourcen
Beim Konfigurieren von API-Ressourcen erwartet die AddInMemoryApiResources
-Methode eine IEnumerable<ApiResource>
-Sammlung. Das folgende Codebeispiel zeigt die GetApis
-Methode, die diese Sammlung in der eShopOnContainers-Referenzanwendung bereitstellt:
public static IEnumerable<ApiResource> GetApis()
{
return new List<ApiResource>
{
new ApiResource("orders", "Orders Service"),
new ApiResource("basket", "Basket Service")
};
}
Diese Methode gibt an, dass IdentityServer die Bestellungen und Warenkorb-APIs schützen soll. Daher sind verwaltete Identitätsserver-Zugriffstoken erforderlich, wenn Aufrufe an diese APIs getätigt werden. Weitere Informationen zum ApiResource
-Typ finden Sie unter API-Ressource in der IdentityServer 4-Dokumentation.
Konfigurieren von Identitätsressourcen
Beim Konfigurieren von Identitätsressourcen erwartet die AddInMemoryIdentityResources
-Methode eine IEnumerable<IdentityResource>
-Sammlung. Identitätsressourcen sind Daten wie Benutzer-IDs, Namen oder E-Mail-Adressen. Jede Identitätsressource hat einen eindeutigen Namen, und beliebige Anspruchstypen können ihm zugewiesen werden, die dann im Identitätstoken für den Benutzer enthalten sein. Das folgende Codebeispiel zeigt die GetResources
-Methode, die diese Sammlung in der eShopOnContainers-Referenzanwendung bereitstellt:
public static IEnumerable<IdentityResource> GetResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
}
Die OpenID Connect-Spezifikation gibt einige Standardidentitätsressourcen an. Die Mindestanforderung ist, dass eine eindeutige Benutzer-ID ausgegeben werden kann. Hierfür wird die Identitätsressource IdentityResources.OpenId
verfügbar gemacht.
Hinweis
Die IdentityResources
Klasse unterstützt alle Bereiche, die in der OpenID Connect-Spezifikation definiert sind (Openid, E-Mail, Profil, Telefon und Adresse).
IdentityServer unterstützt auch das Definieren benutzerdefinierter Identitätsressourcen. Weitere Informationen zum IdentityResource
Typ finden Sie in der IdentityServer 4-Dokumentation .
Configuring Clients (Konfigurieren von Clients)
Clients sind Anwendungen, die Token von IdentityServer anfordern können. In der Regel müssen mindestens die folgenden Einstellungen für jeden Client definiert werden:
- Eine eindeutige Client-ID
- Die zulässigen Interaktionen mit dem Tokendienst (auch als Gewährungstyp bezeichnet)
- Der Speicherort, an den Identitäts- und Zugriffstoken gesendet werden (auch als Umleitungs-URI bezeichnet)
- Eine Liste der Ressourcen, auf die der Client Zugriff hat (auch als Bereiche bezeichnet)
Beim Konfigurieren von Clients erwartet die AddInMemoryClients
-Methode eine IEnumerable<Client>
-Sammlung. Das folgende Codebeispiel zeigt die Konfiguration für die mobile eShopOnContainers-App in der GetClients
Methode, die diese Auflistung in der Referenzanwendung "eShopOnContainers" bereitstellt:
public static IEnumerable<Client> GetClients(Dictionary<string,string> clientsUrl)
{
return new List<Client>
{
...
new Client
{
ClientId = "xamarin",
ClientName = "eShop Xamarin OpenId Client",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { clientsUrl["Xamarin"] },
RequireConsent = false,
RequirePkce = true,
PostLogoutRedirectUris = { $"{clientsUrl["Xamarin"]}/Account/Redirecting" },
AllowedCorsOrigins = { "http://eshopxamarin" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
"orders",
"basket"
},
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true
},
...
};
}
Diese Konfiguration gibt die Daten für die folgenden Eigenschaften an:
ClientId
: Eine eindeutige ID für den Client.ClientName
: Der Clientanzeigename, der für die Protokollierung und den Zustimmungsbildschirm verwendet wird.AllowedGrantTypes
: Gibt an, wie ein Client mit IdentityServer interagieren möchte. Weitere Informationen finden Sie unter Konfigurieren des Authentifizierungsflusses.ClientSecrets
: Gibt die geheimen Clientschlüsselanmeldeinformationen an, die beim Anfordern von Token vom Tokenendpunkt verwendet werden.RedirectUris
: Gibt die zulässigen URIs an, an die Token oder Autorisierungscodes zurückgegeben werden sollen.RequireConsent
: Gibt an, ob ein Zustimmungsbildschirm erforderlich ist.RequirePkce
: Gibt an, ob Clients, die einen Autorisierungscode verwenden, einen Proof Key senden müssen.PostLogoutRedirectUris
: Gibt die zulässigen URIs an, an die nach dem Abmelden umgeleitet werden soll.AllowedCorsOrigins
: Gibt den Ursprung des Clients an, damit IdentityServer ursprungsübergreifende Aufrufe vom Ursprung zulassen kann.AllowedScopes
: Gibt die Ressourcen an, auf die der Client zugreifen kann. Standardmäßig hat ein Client keinen Zugriff auf Ressourcen.AllowOfflineAccess
: Gibt an, ob der Client Aktualisierungstoken anfordern kann.
Konfigurieren des Authentifizierungsflusses
Der Authentifizierungsflow zwischen einem Client und IdentityServer kann konfiguriert werden, indem die Gewährungstypen in der Client.AllowedGrantTypes
-Eigenschaft angegeben werden. Die OpenID Connect- und OAuth 2.0-Spezifikationen definieren eine Reihe von Authentifizierungsflüssen, darunter:
- Implizit. Dieser Flow ist für browserbasierte Anwendungen optimiert und sollte entweder nur für benutzerspezifische Authentifizierungsanforderungen oder für Authentifizierungs- und Zugriffstokenanforderungen verwendet werden. Alle Token werden über den Browser übertragen, sodass erweiterte Features wie Aktualisierungstoken nicht zulässig sind.
- Autorisierungscode: Dieser Flow ermöglicht das Abrufen von Token in einem Backchannel statt im Frontchannel des Browsers und unterstützt gleichzeitig die Clientauthentifizierung.
- Hybrid. Dieser Flow ist eine Kombination aus den impliziten und Autorisierungscode-Gewährungstypen. Das Identitätstoken wird über den Browserkanal übertragen und enthält die signierte Protokollantwort zusammen mit anderen Artefakten wie dem Autorisierungscode. Nach erfolgreicher Überprüfung der Antwort sollte der Zurückkanal verwendet werden, um das Zugriffs- und Aktualisierungstoken abzurufen.
Tipp
Verwenden Sie den Hybridauthentifizierungsfluss. Der Hybridauthentifizierungsflow entschärft verschiedene Angriffe auf Browserkanal und ist der empfohlene Flow für native Anwendungen, die Zugriffstoken (und möglicherweise Aktualisierungstoken) abrufen möchten.
Weitere Informationen zu Authentifizierungsflows finden Sie unter Gewährungstypen in der IdentityServer 4-Dokumentation.
Durchführen der Authentifizierung
Damit IdentityServer Token im Namen eines Benutzers ausstellen kann, muss sich der Benutzer bei IdentityServer anmelden. IdentityServer hat jedoch keine Benutzeroberfläche oder Datenbank für die Authentifizierung. Daher wird in der Referenzanwendung „eShopOnContainers“ ASP.NET Core Identity für diesen Zweck verwendet.
Die mobile eShopOnContainers-App authentifiziert sich mit IdentityServer mit dem Hybridauthentifizierungsfluss, der in Abbildung 9-2 dargestellt wird.
Abbildung 9-2: Allgemeine Übersicht über den Anmeldevorgang
Eine Anmeldeanforderung wird an .<base endpoint>:5105/connect/authorize
Nach erfolgreicher Authentifizierung gibt IdentityServer eine Authentifizierungsantwort zurück, die einen Autorisierungscode und ein Identitätstoken enthält. Der Autorisierungscode wird dann an <base endpoint>:5105/connect/token
gesendet, an das mit Zugriffs-, Identitäts- und Aktualisierungstoken reagiert.
Die mobile eShopOnContainers-App meldet sich von IdentityServer ab, indem sie eine Anforderung mit zusätzlichen Parametern sendet <base endpoint>:5105/connect/endsession
. Nachdem die Abmeldung erfolgt, antwortet IdentityServer, indem ein Umleitungs-URI nach dem Abmelden zurück an die mobile App gesendet wird. Abbildung 9-3 veranschaulicht diesen Prozess.
Abbildung 9-3: Allgemeine Übersicht über den Abmeldungsprozess
In der mobilen eShopOnContainers-App wird die Kommunikation mit IdentityServer von der IdentityService
Klasse ausgeführt, die die IIdentityService
Schnittstelle implementiert. Diese Schnittstelle gibt an, dass eine implementierende Klasse die folgenden Methoden CreateAuthorizationRequest
, CreateLogoutRequest
und GetTokenAsync
bereitstellen muss.
Anmelden
Wenn der Benutzer auf die Schaltfläche "LOGIN " auf der LoginView
Schaltfläche tippt, wird die SignInCommand
Klasse LoginViewModel
ausgeführt, die wiederum die SignInAsync
Methode ausführt. Im folgenden Codebeispiel wird diese Methode veranschaulicht:
private async Task SignInAsync()
{
...
LoginUrl = _identityService.CreateAuthorizationRequest();
IsLogin = true;
...
}
Diese Methode ruft die CreateAuthorizationRequest
Methode in der IdentityService
Klasse auf, die im folgenden Codebeispiel dargestellt wird:
public string CreateAuthorizationRequest()
{
// Create URI to authorization endpoint
var authorizeRequest = new AuthorizeRequest(GlobalSetting.Instance.IdentityEndpoint);
// Dictionary with values for the authorize request
var dic = new Dictionary<string, string>();
dic.Add("client_id", GlobalSetting.Instance.ClientId);
dic.Add("client_secret", GlobalSetting.Instance.ClientSecret);
dic.Add("response_type", "code id_token");
dic.Add("scope", "openid profile basket orders locations marketing offline_access");
dic.Add("redirect_uri", GlobalSetting.Instance.Callback);
dic.Add("nonce", Guid.NewGuid().ToString("N"));
dic.Add("code_challenge", CreateCodeChallenge());
dic.Add("code_challenge_method", "S256");
// Add CSRF token to protect against cross-site request forgery attacks.
var currentCSRFToken = Guid.NewGuid().ToString("N");
dic.Add("state", currentCSRFToken);
var authorizeUri = authorizeRequest.Create(dic);
return authorizeUri;
}
Diese Methode erstellt den URI für den Autorisierungsendpunkt von IdentityServer mit den erforderlichen Parametern. Der Autorisierungsendpunkt befindet sich unter /connect/authorize
an Port 5105 des Basisendpunkts, der als Benutzereinstellung verfügbar gemacht wird. Weitere Informationen zu Benutzereinstellungen finden Sie unter Konfigurationsverwaltung.
Hinweis
Die Angriffsfläche der mobilen eShopOnContainers-App wird durch die Implementierung der Proof Key for Code Exchange (PKCE)-Erweiterung in OAuth reduziert. PKCE schützt den Autorisierungscode vor der Verwendung, wenn er abgefangen wird. Hierfür generiert der Client einen geheimen Prüfmechanismus, dessen Hash an die Autorisierungsanforderung übergeben wird und der beim Einlösen des Autorisierungscodes ungehasht angezeigt wird. Weitere Informationen zu PKCE finden Sie unter Proof Key for Code Exchange durch öffentliche OAuth-Clients auf der Website der Internet Engineering Task Force.
Der zurückgegebene URI wird in der LoginUrl
-Eigenschaft der LoginViewModel
-Klasse gespeichert. Wenn die IsLogin
Eigenschaft wird true
, wird das WebView
In-In LoginView
sichtbar. Die WebView
Daten binden ihre Source
Eigenschaft an die LoginUrl
Eigenschaft der LoginViewModel
Klasse und stellen daher eine Anmeldeanforderung an IdentityServer vor, wenn die LoginUrl
Eigenschaft auf den Autorisierungsendpunkt von IdentityServer festgelegt ist. Wenn IdentityServer diese Anforderung empfängt und der Benutzer nicht authentifiziert wird, wird er WebView
an die konfigurierte Anmeldeseite umgeleitet, die in Abbildung 9-4 dargestellt wird.
Abbildung 9-4: Anmeldeseite, die von webView angezeigt wird
Sobald die Anmeldung erfolgt ist, wird WebView
an einen Rückgabe-URI umgeleitet. Durch die WebView
-Navigation wird die NavigateAsync
-Methode in der LoginViewModel
-Klasse ausgeführt, was im folgenden Codebeispiel gezeigt wird:
private async Task NavigateAsync(string url)
{
...
var authResponse = new AuthorizeResponse(url);
if (!string.IsNullOrWhiteSpace(authResponse.Code))
{
var userToken = await _identityService.GetTokenAsync(authResponse.Code);
string accessToken = userToken.AccessToken;
if (!string.IsNullOrWhiteSpace(accessToken))
{
Settings.AuthAccessToken = accessToken;
Settings.AuthIdToken = authResponse.IdentityToken;
await NavigationService.NavigateToAsync<MainViewModel>();
await NavigationService.RemoveLastFromBackStackAsync();
}
}
...
}
Diese Methode analysiert die Authentifizierungsantwort, die im Rückgabe-URI enthalten ist, und vorausgesetzt, dass ein gültiger Autorisierungscode vorhanden ist, sendet sie eine Anforderung an den Tokenendpunkt von IdentityServer, das Übergeben des Autorisierungscodes, den geheimen PKCE-Prüfer und andere erforderliche Parameter. Der Tokenendpunkt befindet sich unter /connect/token
an Port 5105 des Basisendpunkts, der als Benutzereinstellung verfügbar gemacht wird. Weitere Informationen zu Benutzereinstellungen finden Sie unter Konfigurationsverwaltung.
Tipp
Überprüfen der Rückgabe-URIs. Obwohl die mobile eShopOnContainers-App den Rückgabe-URI nicht überprüft, empfiehlt es sich, zu überprüfen, ob der Rückgabe-URI auf einen bekannten Speicherort verweist, um Open-Redirect-Angriffe zu verhindern.
Wenn der Tokenendpunkt einen gültigen Autorisierungscode und einen PKCE-Geheimnisprüfmechanismus empfängt, antwortet er mit einem Zugriffstoken, Identitätstoken und Aktualisierungstoken. Das Zugriffstoken (das den Zugriff auf API-Ressourcen zulässt) und das Identitätstoken werden dann als Anwendungseinstellungen gespeichert, und die Seitennavigation wird ausgeführt. Daher ist der Gesamteffekt in der mobilen eShopOnContainers-App: Vorausgesetzt, dass Benutzer sich erfolgreich bei IdentityServer authentifizieren können, werden sie zu der MainView
Seite navigiert, die TabbedPage
als CatalogView
ausgewählte Registerkarte angezeigt wird.
Weitere Informationen zur Seitennavigation finden Sie unter Navigation. Informationen dazu, wie die Navigation bewirkt, dass WebView
eine Ansichtsmodellmethode ausgeführt wird, finden Sie unter "Aufrufen der Navigation mithilfe von Verhalten". Informationen zu Anwendungseinstellungen finden Sie unter Configuration Management.
Hinweis
Die eShopOnContainers ermöglichen auch eine simulierte Anmeldung, wenn die App so konfiguriert ist, dass simulierte Dienste in der SettingsView
App verwendet werden. In diesem Modus kommuniziert die App nicht mit IdentityServer, sondern ermöglicht es dem Benutzer, sich mit anmeldeinformationen anzumelden.
Abmelden
Wenn der Benutzer auf die Schaltfläche "ABMELDEn " in der ProfileView
Klasse tippt, wird die LogoutCommand
Klasse ProfileViewModel
ausgeführt, wodurch wiederum die LogoutAsync
Methode ausgeführt wird. Diese Methode führt die Seitennavigation zur Seite LoginView
aus und übergibt eine LogoutParameter
-Instanz, deren Parameter auf true
festgelegt ist. Weitere Informationen zum Übergeben von Parametern während der Seitennavigation finden Sie unter Übergeben von Parametern während der Navigation.
Wenn eine Ansicht erstellt und zu dieser navigiert wird, wird die InitializeAsync
-Methode des zugeordneten Ansichtsmodells ausgeführt, wodurch dann die Logout
-Methode der LoginViewModel
-Klasse ausgeführt wird. Dieser Ablauf wird im folgenden Codebeispiel veranschaulicht:
private void Logout()
{
var authIdToken = Settings.AuthIdToken;
var logoutRequest = _identityService.CreateLogoutRequest(authIdToken);
if (!string.IsNullOrEmpty(logoutRequest))
{
// Logout
LoginUrl = logoutRequest;
}
...
}
Diese Methode ruft die CreateLogoutRequest
-Methode in der IdentityService
-Klasse auf und übergibt das aus den Anwendungseinstellungen abgerufene Identitätstoken als Parameter. Weitere Informationen zu Anwendungseinstellungen finden Sie unter Configuration Management. Die CreateLogoutRequest
-Methode wird in folgendem Codebeispiel veranschaulicht:
public string CreateLogoutRequest(string token)
{
...
return string.Format("{0}?id_token_hint={1}&post_logout_redirect_uri={2}",
GlobalSetting.Instance.LogoutEndpoint,
token,
GlobalSetting.Instance.LogoutCallback);
}
Diese Methode erstellt den URI zum Endpunkt der IdentityServer-Sitzung mit den erforderlichen Parametern. Der Endpunkt zum Beenden der Sitzung befindet sich unter /connect/endsession
an Port 5105 des Basisendpunkts, der als Benutzereinstellung verfügbar gemacht wird. Weitere Informationen zu Benutzereinstellungen finden Sie unter Konfigurationsverwaltung.
Der zurückgegebene URI wird in der LoginUrl
-Eigenschaft der LoginViewModel
-Klasse gespeichert. IsLogin
Die Eigenschaft ist true
zwar WebView
LoginView
sichtbar. Die WebView
Daten binden ihre Source
Eigenschaft an die LoginUrl
Eigenschaft der LoginViewModel
Klasse und stellen daher eine Abmeldeanforderung an IdentityServer vor, wenn die LoginUrl
Eigenschaft auf den Endpunkt der Endsitzung von IdentityServer festgelegt ist. Wenn IdentityServer diese Anforderung empfängt, sofern der Benutzer angemeldet ist, tritt die Abmeldung auf. Die Authentifizierung wird mit einem Cookie nachverfolgt, das von der Middleware für die Cookieauthentifizierung von ASP.NET Core verwaltet wird. Daher entfernt das Abmelden von IdentityServer das Authentifizierungscookies und sendet einen Umleitungs-URI nach dem Abmelden an den Client zurück.
In der mobilen App wird der WebView
Umleitungs-URI nach der Abmeldung umgeleitet. Durch die WebView
-Navigation wird die NavigateAsync
-Methode in der LoginViewModel
-Klasse ausgeführt, was im folgenden Codebeispiel gezeigt wird:
private async Task NavigateAsync(string url)
{
...
Settings.AuthAccessToken = string.Empty;
Settings.AuthIdToken = string.Empty;
IsLogin = false;
LoginUrl = _identityService.CreateAuthorizationRequest();
...
}
Diese Methode löscht sowohl das Identitätstoken als auch das Zugriffstoken aus den Anwendungseinstellungen und legt die IsLogin
Eigenschaft auf false
fest, wodurch die WebView
LoginView
Seite unsichtbar wird. Schließlich wird die LoginUrl
-Eigenschaft auf den URI des Autorisierungsendpunkts von IdentityServer mit den erforderlichen Parametern festgelegt, um die nächste Benutzeranmeldung vorzubereiten.
Weitere Informationen zur Seitennavigation finden Sie unter Navigation. Informationen dazu, wie die Navigation bewirkt, dass WebView
eine Ansichtsmodellmethode ausgeführt wird, finden Sie unter "Aufrufen der Navigation mithilfe von Verhalten". Informationen zu Anwendungseinstellungen finden Sie unter Configuration Management.
Hinweis
Die eShopOnContainers ermöglichen auch eine simulierte Abmeldung, wenn die App so konfiguriert ist, dass simulierte Dienste in der SettingsView verwendet werden. In diesem Modus kommuniziert die App nicht mit IdentityServer und löscht stattdessen alle gespeicherten Token aus den Anwendungseinstellungen.
Autorisierung
Nach der Authentifizierung müssen ASP.NET Core-Web-APIs häufig den Zugriff autorisieren, wodurch ein Dienst APIs für einige authentifizierte Benutzer, aber nicht für alle verfügbar macht.
Das Einschränken des Zugriffs auf eine ASP.NET Core MVC-Route kann erreicht werden, indem ein Authorize-Attribut auf einen Controller oder eine Aktion angewendet wird, wodurch der Zugriff auf den Controller oder die Aktion auf authentifizierte Benutzer beschränkt wird, wie im folgenden Codebeispiel gezeigt:
[Authorize]
public class BasketController : Controller
{
...
}
Wenn ein nicht autorisierter Benutzer versucht, auf einen Controller oder eine Aktion zuzugreifen, der mit dem Authorize
Attribut gekennzeichnet ist, gibt das MVC-Framework einen HTTP-Statuscode 401 (nicht autorisiert) zurück.
Hinweis
Parameter können für das Authorize
Attribut angegeben werden, um eine API auf bestimmte Benutzer einzuschränken. Weitere Informationen finden Sie unter Autorisierung.
IdentityServer kann in den Autorisierungsworkflow integriert werden, sodass die bereitgestellten Zugriffstoken die Autorisierung steuern. Dieser Ansatz ist in Abbildung 9-5 dargestellt.
Abbildung 9-5: Autorisierung nach Zugriffstoken
Die mobile eShopOnContainers-App kommuniziert mit dem Identitäts-Microservice und fordert ein Zugriffstoken als Teil des Authentifizierungsprozesses an. Das Zugriffstoken wird dann an die APIs weitergeleitet, die von den Bestell- und Warenkorbmicroservices im Rahmen der Zugriffsanforderungen verfügbar gemacht werden. Zugriffstoken enthalten Informationen über den Client und den Benutzer. APIs verwenden diese Informationen dann, um den Zugriff auf ihre Daten zu autorisieren. Informationen zum Konfigurieren von IdentityServer zum Schutz von APIs finden Sie unter Konfigurieren von API-Ressourcen.
Konfigurieren von IdentityServer zum Durchführen der Autorisierung
Um die Autorisierung mit IdentityServer durchzuführen, muss die zugehörige Autorisierungsmiddleware der HTTP-Anforderungspipeline der Webanwendung hinzugefügt werden. Die Middleware wird in der ConfigureAuth
Methode der Webanwendungsklasse Startup
hinzugefügt, die von der Configure
Methode aufgerufen wird, und wird im folgenden Codebeispiel aus der eShopOnContainers-Referenzanwendung veranschaulicht:
protected virtual void ConfigureAuth(IApplicationBuilder app)
{
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = identityUrl.ToString(),
ScopeName = "basket",
RequireHttpsMetadata = false
});
}
Diese Methode stellt sicher, dass nur mit einem gültigen Zugriffstoken auf die API zugegriffen werden kann. Die Middleware überprüft das eingehende Token, um sicherzustellen, dass es von einem vertrauenswürdigen Aussteller gesendet wird, und überprüft, ob das Token gültig ist, um mit der API verwendet zu werden, die es empfängt. Daher gibt das Browsen zum Sortier- oder Korbcontroller einen HTTP-Statuscode 401 (nicht autorisiert) zurück, der angibt, dass ein Zugriffstoken erforderlich ist.
Hinweis
Die Autorisierungsmiddleware von IdentityServer muss der HTTP-Anforderungspipeline der Webanwendung hinzugefügt werden, bevor MVC mit app.UseMvc()
oder app.UseMvcWithDefaultRoute()
hinzugefügt wird.
Erstellen von Zugriffsanforderungen an APIs
Beim Senden von Anforderungen an die Sortierung und den Korb microservices muss das Zugriffstoken, das während des Authentifizierungsprozesses von IdentityServer abgerufen wird, in die Anforderung aufgenommen werden, wie im folgenden Codebeispiel gezeigt:
var authToken = Settings.AuthAccessToken;
Order = await _ordersService.GetOrderAsync(Convert.ToInt32(order.OrderNumber), authToken);
Das Zugriffstoken wird als Anwendungseinstellung gespeichert und aus plattformspezifischem Speicher abgerufen und im Aufruf der GetOrderAsync
Methode in der OrderService
Klasse enthalten.
Ebenso muss das Zugriffstoken beim Senden von Daten an eine geschützte IdentityServer-API eingeschlossen werden, wie im folgenden Codebeispiel zu sehen ist:
var authToken = Settings.AuthAccessToken;
await _basketService.UpdateBasketAsync(new CustomerBasket
{
BuyerId = userInfo.UserId,
Items = BasketItems.ToList()
}, authToken);
Das Zugriffstoken wird aus plattformspezifischem Speicher abgerufen und im Aufruf der UpdateBasketAsync
Methode in der BasketService
Klasse enthalten.
Die RequestProvider
Klasse in der mobilen eShopOnContainers-App verwendet die HttpClient
Klasse, um Anforderungen an die RESTful-APIs zu stellen, die von der eShopOnContainers-Referenzanwendung verfügbar gemacht werden. Wenn Sie Anforderungen an die Bestell- und Warenkorb-APIs senden, die eine Autorisierung erfordern, muss ein gültiges Zugriffstoken in die Anforderung eingeschlossen werden. Dies wird durch Hinzufügen des Zugriffstokens zu den Headern der HttpClient
Instanz erreicht, wie im folgenden Codebeispiel veranschaulicht:
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
Die DefaultRequestHeaders
-Eigenschaft der HttpClient
-Klasse macht die Header verfügbar, die mit jeder Anforderung gesendet werden, und das Zugriffstoken wird dem Header Authorization
mit dem Präfix Bearer
hinzugefügt. Wenn die Anforderung an eine RESTful-API gesendet wird, wird der Wert des Authorization
Headers extrahiert und überprüft, um sicherzustellen, dass sie von einem vertrauenswürdigen Aussteller gesendet wird und verwendet wird, um zu bestimmen, ob der Benutzer über die Berechtigung zum Aufrufen der API verfügt, die sie empfängt.
Weitere Informationen dazu, wie die mobile eShopOnContainers-App Webanforderungen sendet, finden Sie unter "Zugreifen auf Remotedaten".
Zusammenfassung
Es gibt viele Ansätze zum Integrieren von Authentifizierung und Autorisierung in eine Xamarin.Forms App, die mit einer ASP.NET MVC-Webanwendung kommuniziert. Die mobile eShopOnContainers-App führt Authentifizierung und Autorisierung mit einem containerisierten Identitäts-Microservice durch, der IdentityServer 4 verwendet. IdentityServer ist ein Open-Source-Framework mit OpenID Connect und OAuth 2.0 für ASP.NET Core, das mit ASP.NET Core Identity integriert werden kann, um die Bearertokenauthentifizierung durchzuführen.
Die mobile App fordert Sicherheitstoken von IdentityServer an, entweder für die Authentifizierung eines Benutzers oder für den Zugriff auf eine Ressource. Beim Zugriff auf eine Ressource muss ein Zugriffstoken in die Anforderung an APIs eingeschlossen werden, die eine Autorisierung erfordern. Die Middleware von IdentityServer überprüft eingehende Zugriffstoken, um sicherzustellen, dass sie von einem vertrauenswürdigen Aussteller gesendet werden und dass sie mit der API verwendet werden, die sie empfängt.