Mit OAuth2-Bereichen arbeiten

In diesem Thema wird erläutert, wie OAuth 2.0-Bereiche in Apigee verwendet werden.

Was ist ein OAuth2-Bereich?

OAuth 2.0-Bereiche bieten die Möglichkeit, den Umfang des Zugriffs zu beschränken, der einem Zugriffstoken gewährt wird. Beispiel: Ein Zugriffstoken, das an eine Clientanwendung ausgegeben wird, kann READ- und WRITE-Zugriff auf geschützte Ressourcen oder nur READ-Zugriff gewähren. Sie können APIs implementieren, um alle Bereiche oder Kombinationen aus Bereichen zu erzwingen. Wenn dann ein Client ein Token mit dem READ-Bereich erhält und versucht, einen API-Endpunkt aufzurufen, für den WRITE-Zugriff erforderlich ist, schlägt der Aufruf fehl.

In diesem Thema wird erläutert, wie Zugriffstokens Bereiche zugewiesen werden und wie Apigee OAuth 2.0-Bereiche erzwingt. Nachdem Sie dieses Thema gelesen haben, können Sie Bereiche mit Zuversicht verwenden.

Wie werden Bereiche zu Zugriffstokens zugewiesen?

Wenn Apigee ein Zugriffstoken generiert, wird diesem möglicherweise ein Bereich zugewiesen. Machen Sie sich zum Verständnis zuerst mit folgenden Apigee-Entitäten vertraut: API-Produkte, Entwickler und Entwickleranwendungen. Eine Einführung finden Sie unter Einführung in die Veröffentlichung. Wir empfehlen dir, dieses Material falls nötig zu lesen, bevor du fortfahren.

Ein Zugriffstoken ist ein langer String mit zufällig dargestellten Zeichen, anhand dessen Apigee eingehende API-Anfragen verifizieren kann. Betrachten Sie das Token als eine Art Ersatz für typische Anmeldedaten, die aus einem Nutzernamen und einem Passwort bestehen. Technisch gesehen ist das Token ein Schlüssel, der sich auf eine Sammlung von Metadaten bezieht, die in etwa so aussehen:

{
  "issued_at" : "1416962591727",
  "application_name" : "0d3e1d41-a59f-4d74-957e-d4e3275d4781",
  "scope" : "A",
  "status" : "approved",
  "api_product_list" : "[scopecheck1-bs0cSuqS9y]",
  "expires_in" : "1799", //--in seconds
  "developer.email" : "scopecheck1-AdBmANhsag@apigee.com",
  "organization_id" : "0",
  "token_type" : "BearerToken",
  "client_id" : "eTtB7w5lvk3DnOZNGReBlvGvIAeAywun",
  "access_token" : "ODm47ris5AlEty8TDc1itwYPe5MW",
  "organization_name" : "wwitman",
  "refresh_token_expires_in" : "0", //--in seconds
  "refresh_count" : "0"
}

Die Metadaten des Tokens enthalten den String des tatsächlichen Zugriffstokens, Ablaufinformationen, die Identifizierung der Entwickleranwendung, des Entwicklers und der mit dem Token verknüpften Produkte. Die Metadaten enthalten auch einen "Bereich".

Wie erhält das Token seinen Bereich?

Als Erstes müssen Sie wissen, dass jedem Produkt in einer Entwickleranwendung null oder mehr Bereiche zugewiesen werden können. Diese Bereiche können zugewiesen werden, wenn das Produkt erstellt wird, oder später hinzugefügt werden. Sie sind als Liste mit Namen vorhanden und in den Metadaten des jeweiligen Produkts enthalten.

Wenn Sie eine Entwickleranwendung erstellen und ihr Produkte hinzufügen, prüft Apigee alle Produkte in der Entwickleranwendung und erstellt eine Liste aller Bereiche für diese Produkte (die Masterliste oder die globale Bereichsliste der Anwendung: eine Vereinigung aller erkannten Bereiche).

.

Wenn eine Clientanwendung ein Zugriffstoken von Apigee anfordert, kann sie optional angeben, welche Bereiche mit diesem Token verknüpft werden sollen. Die folgende Anfrage fragt beispielsweise nach dem Bereich "A". Der Client fordert also an, dass der Autorisierungsserver (Apigee) ein Zugriffstoken mit dem Bereich "A" generiert (damit erhält die App die Berechtigung zum Aufrufen von APIs mit dem Bereich "A"). Die Anwendung sendet eine POST-Anfrage wie diese:

curl -i -X POST -H Authorization: Basic Mg12YTk2UkEIyIBCrtro1QpIG \
  -H content-type:application/x-www-form-urlencoded \
  https://apitest.acme.com/oauth/token?grant_type=client_credentials&scope=A

Was passiert dann?

Wenn Apigee diese Anfrage erhält, weiß sie, welche Anwendung die Anfrage durchführt und welche Entwickleranwendung den Client registriert hat. Die Client-ID und der Clientschlüssel werden im grundlegenden Authentifizierungsheader codiert. Da der Abfrageparameter scope enthalten ist, muss Apigee entscheiden, ob eines der mit der Entwickleranwendung verknüpften API-Produkte den Bereich „A“ hat. In diesem Fall wird ein Zugriffstoken mit dem Bereich "A" generiert. Eine weitere Möglichkeit, dies zu betrachten, ist der Suchparameter des Bereichs als eine Art Filter. Wenn die Entwickleranwendung die Bereiche "A, B, X" erkennt und der Suchparameter "scope=X Y Z" angibt, wird dem Token nur der Bereich "X" zugewiesen.

Was geschieht, wenn der Client keinen Bereichsparameter anhängt? In diesem Fall generiert Apigee ein Token, das alle Bereiche enthält, die von der Entwickler-App erkannt werden. Bitte beachten Sie, dass das Standardverhalten darin besteht, ein Zugriffstoken zurückzugeben, das die Vereinigung aller Bereiche für alle in der Entwickler-App enthaltenen Produkte umfasst.

Wenn keines der mit einer Entwickleranwendung verknüpften Produkte Bereiche umfasst und ein Token einen Bereich hat, schlagen Aufrufe mit diesem Token fehl.

Nehmen wir an, eine Entwickler-App erkennt diese Bereiche: A B C D. Dies ist die Masterliste der Bereiche für die Anwendung. Beispiel: Ein Produkt in der Anwendung hat die Bereiche A und B und ein zweites die Bereiche C und D oder eine beliebige Kombination. Wenn der Client den Parameter scope nicht angibt oder wenn er den Bereichsparameter ohne Wert angibt, werden dem Token alle vier Bereiche zugewiesen: A, B, C und D. Auch das Token erhält eine Reihe von Bereichen, die die Vereinigung aller Bereiche darstellt, die von der Entwickler-App erkannt werden.

Es gibt einen weiteren Fall, in dem nach Standardverhalten ein Zugriffstoken mit allen erkannten Bereichen zurückgegeben wird. Dies geschieht, wenn in der GenerateAccessToken-Richtlinie (die Apigee-Richtlinie, die Zugriffstokens generiert) kein <Scope>-Element angegeben ist. In der folgenden GenerateAccessToken-Richtlinie beispielsweise ist <Scope> angegeben. Wenn dieses <Scope>-Element fehlt oder vorhanden, aber leer ist, wird das Standardverhalten ausgeführt.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-GenerateAccessToken">
    <DisplayName>OAuthV2 - Generate Access Token</DisplayName>
    <Attributes>
      <Attribute name='hello' ref='system.time' display='false'>value1</Attribute>
    </Attributes>
    <Scope>request.queryparam.scope</Scope> 
    <GrantType>request.formparam.grant_type</GrantType>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>GenerateAccessToken</Operation>
    <SupportedGrantTypes>
      <GrantType>client_credentials</GrantType>
    </SupportedGrantTypes>
  <GenerateResponse enabled="true"/>
</OAuthV2>

Wie werden Bereiche erzwungen?

Beachten Sie zuerst, dass Zugriffstoken in Apigee mit der OAuthV2-Richtlinie validiert werden (in der Regel zu Beginn eines Proxyablaufs). Für die Richtlinie muss der Vorgang „VerifyAccessToken“ angegeben sein. Sehen Sie sich diese Richtlinie an:

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenA">
    <DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>VerifyAccessToken</Operation>
    <Scope>A</Scope> <!-- Optional: space-separated list of scope names. -->
    <GenerateResponse enabled="true"/>
</OAuthV2>

Beachten Sie das <Scope>-Element. Damit wird angegeben, welche Bereiche die Richtlinie akzeptiert.

In diesem Beispiel ist die Richtlinie nur erfolgreich, wenn das Zugriffstoken den Bereich "A" enthält. Wenn dieses <Scope>-Element weggelassen wird oder keinen Wert hat, ignoriert die Richtlinie den Bereich des Zugriffstokens.

Jetzt haben Sie die Möglichkeit, Zugriffstokens auf der Grundlage von Bereichen zu validieren. Sie können Ihre APIs so entwerfen, dass bestimmte Bereiche erzwungen werden. Dazu entwerfen Sie benutzerdefinierte Abläufe an die bereichssensitive VerifyAccessToken-Richtlinien angehängt sind.

Nehmen wir an, dass in der API ein Ablauf für den Endpunkt /resourceA definiert ist:

<Flow name="resourceA">
            <Condition>(proxy.pathsuffix MatchesPath "/resourceA") and (request.verb = "GET")</Condition>
            <Description>Get a resource A</Description>
            <Request>
                <Step>
                    <Name>OAuthV2-VerifyAccessTokenA</Name>
                </Step>
            </Request>
            <Response>
                <Step>
                    <Name>AssignMessage-CreateResponse</Name>
                </Step>
            </Response>
        </Flow>

Wenn dieser Ablauf ausgelöst wird (eine Anfrage geht ein und enthält /resourceA im Pfadsuffix), wird die OAuthV2-VerifyAccessTokenA-Richtlinie sofort aufgerufen. Diese Richtlinie prüft, ob das Zugriffstoken gültig ist und ermittelt, welche Bereiche das Token unterstützt. Wenn die Richtlinie wie im folgenden Beispiel konfiguriert ist, mit <Scope>A</Scope>, funktioniert die Richtlinie nur dann erfolgreich, wenn das Zugriffstoken den Bereich "A" hat. Andernfalls wird ein Fehler zurückgegeben.

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenA">
    <DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>VerifyAccessToken</Operation>
    <Scope>A</Scope>
    <GenerateResponse enabled="true"/>
</OAuthV2>

Zusammenfassend lässt sich sagen, dass API-Entwickler verantwortlich sind für die Integration der Erzwingung von Bereichen in ihre APIs. Dazu werden benutzerdefinierte Abläufe für die Verarbeitung bestimmter Bereiche erstellt und VerifyAccessToken-Richtlinien angehängt, um diese Bereiche zu erzwingen.

Codebeispiele

Betrachten wir nun einige Beispiele für API-Aufrufe. Anhand dieser Beispiele wird veranschaulicht, wie Tokens Bereiche erhalten und wie Bereiche erzwungen werden.

Standardfall

Angenommen, Sie haben eine Entwickler-App mit Produkten und die Vereinigung der Bereiche dieser Produkte lauten: A, B und C. Dieser API-Aufruf fordert ein Zugriffstoken an, gibt jedoch keinen Bereichsabfrageparameter an.

curl -X POST -H content-type:application/x-www-form-urlencoded \
  https://apitest.acme.com/scopecheck1/token?grant_type=client_credentials

In diesem Fall erhält das generierte Token die Bereiche A, B und C (Standardverhalten). Die Metadaten des Tokens sehen in etwa so aus:

{
  "issued_at" : "1417016208588",
  "application_name" : "eb1a0333-5775-4116-9eb2-c36075ddc360",
  "scope" : "A B C",
  "status" : "approved",
  "api_product_list" : "[scopecheck1-yEgQbQqjRR]",
  "expires_in" : "1799", //--in seconds
  "developer.email" : "scopecheck1-yxiuHuZcDW@apigee.com",
  "organization_id" : "0",
  "token_type" : "BearerToken",
  "client_id" : "atGFvl3jgA0pJd05rXKHeNAC69naDmpW",
  "access_token" : "MveXpj4UYXol38thNoJYIa8fBGlI",
  "organization_name" : "wwitman",
  "refresh_token_expires_in" : "0", //--in seconds
  "refresh_count" : "0"
}

Angenommen, Sie haben einen API-Endpunkt mit dem Bereich „A“ (d. h. das zugehörige VerifyAccessToken erfordert den Bereich „A“). Hier ist die Richtlinie „VerifyAccessToken“:

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenA">
    <DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>VerifyAccessToken</Operation>
    <Scope>A</Scope>
    <GenerateResponse enabled="true"/>
</OAuthV2>

Hier sehen Sie einen Beispielaufruf und einen Endpunkt, der den Bereich A erzwingt:

curl -X GET -H Authorization: Bearer MveXpj4UYXol38thNoJYIa8fBGlI \
  https://apitest.acme.com/scopecheck1/resourceA

Dieser GET-Aufruf ist erfolgreich:

 {
   "hello" : "Tue, 25 Nov 2014 01:35:53 UTC"
 }

Er ist erfolgreich, da die VerifyAccessToken-Richtlinie, die ausgelöst wird, wenn der Endpunkt aufgerufen wird, den Bereich A erfordert und dem Zugriffstoken die Bereiche A, B und C zugewiesen wurden – das Standardverhalten.

Fall mit Filterung

Angenommen, Sie haben eine Entwickler-App mit Produkten, die die Bereiche A, B, C und X haben. Sie fordern ein Zugriffstoken an und fügen den Abfrageparameter scope ein und zwar so:

curl -i -X POST -H content-type:application/x-www-form-urlencoded \
  'https://apitest.acme.com/oauth/token?grant_type=client_credentials&scope=A X'

In diesem Fall erhält das generierte Token die Bereiche A und X, da sowohl A als auch X gültige Bereiche sind. Denken Sie daran, dass die Entwickleranwendung die Bereiche A, B, C und X erkennt. In diesem Fall filtern Sie die Liste der API-Produkte anhand dieser Bereiche. Wenn ein Produkt den Bereich A oder X hat, können Sie API-Endpunkte konfigurieren, die diese Bereiche erzwingen. Wenn ein Produkt nicht den Bereich A oder X hat, sondern z. B. B, C und Z, können die APIs, die die Bereiche A oder X erzwingen, nicht mit dem Token aufgerufen werden.

Folgendes passiert, wenn Sie die API mit dem neuen Token aufrufen:

curl -X GET -H Authorization: Bearer Rkmqo2UkEIyIBCrtro1QpIG \
  https://apitest.acme.com/scopecheck1/resourceX

Das Zugriffstoken wird vom API-Proxy validiert. Beispiel:

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenX">
    <DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>VerifyAccessToken</Operation>
    <Scope>A X</Scope>
    <GenerateResponse enabled="true"/>
</OAuthV2>

Die GET-Aufruf-Trigger sind erfolgreich und es gibt eine Antwort zurück. Beispiel:

 {
   "hello" : "Tue, 25 Nov 2014 01:35:53 UTC"
 }

Das ist erfolgreich, da die VerifyAccessToken-Richtlinie einen Bereich A oder X erfordert, und das Zugriffstoken einen Bereich A und X enthält. Wenn das Element <Scope> auf "B" gesetzt wäre, würde der Aufruf fehlschlagen.

Fazit

Es ist wichtig zu verstehen, wie Apigee OAuth 2.0-Bereiche verarbeitet. Hier einige wichtige Punkte:

  • Eine Entwickleranwendung "erkennt" die Vereinigung aller Bereiche, die für alle ihre Produkte definiert sind.
  • Wenn eine Anwendung ein Zugriffstoken anfordert, können Sie festlegen, welche Bereiche sie haben sollen. Apigee (der Autorisierungsserver) entscheidet, welche Bereiche dem Zugriffstoken tatsächlich zugewiesen werden. Als Grundlage dienen (a) der angeforderte Bereich und (b) die von der Entwickleranwendung erkannten Bereiche.
  • Wenn Apigee nicht zur Prüfung des Bereichs konfiguriert ist (das Element <Scope> fehlt in der Richtlinie „VerifyAccessToken“ oder ist leer), ist der API-Aufruf erfolgreich, sofern der im Zugriffstoken eingebettete Bereich mit einem der Bereiche übereinstimmt, die von der registrierten Entwickleranwendung erkannt werden (einer der Bereiche in der „Masterliste“ der Bereiche der Anwendung).
  • Wenn mit einem Zugriffstoken keine Bereiche verknüpft sind, ist der Aufruf nur erfolgreich, wenn Apigee den Bereich nicht berücksichtigt (das <Scope>-Element fehlt in der Richtlinie „VerifyAccessToken“ oder ist leer).