Praca z zakresami OAuth2

Przeglądasz dokumentację Apigee Edge.
Otwórz dokumentację Apigee X.
Informacje

W tym temacie omówiono sposób korzystania z zakresów OAuth 2.0 w Apigee Edge.

Co to jest zakres OAuth2?

Zakresy OAuth 2.0 umożliwiają ograniczenie zakresu dostępu przyznawanego tokenowi dostępu. Na przykład token dostępu wydany dla aplikacji klienckiej może otrzymać uprawnienia do ODCZYTU i ZAPISU w przypadku zabezpieczonych zasobów lub uprawnienia tylko do ODCZYTU. Możesz wdrożyć swoje interfejsy API, aby wyegzekwować dowolny zakres lub kombinację zakresów. Jeśli więc klient otrzyma token z zakresem do ODCZYTU i spróbuje wywołać punkt końcowy interfejsu API, który wymaga uprawnień do ZAPISU, wywołanie nie powiedzie się.

W tym temacie omówimy, jak zakresy są przypisywane do tokenów dostępu i jak Apigee Edge wymusza zakresy OAuth 2.0. Po zapoznaniu się z tym tematem dowiesz się, jak bez obaw korzystać z zakresów.

W jaki sposób zakresy są przypisywane do tokenów dostępu?

Gdy Edge wygeneruje token dostępu, może przypisać do niego zakres. Aby zrozumieć, jak to działa, musisz najpierw zapoznać się z tymi elementami Apigee Edge: usługami interfejsu API, deweloperami i aplikacjami deweloperskimi. Wprowadzenie do publikowania znajdziesz w artykule Wprowadzenie do publikowania. Zanim przejdziesz dalej, zalecamy zapoznanie się z tymi materiałami.

Token dostępu to długi ciąg losowo wyglądających znaków, dzięki któremu Edge może zweryfikować przychodzące żądania do interfejsu API (jest to coś w rodzaju typowej nazwy użytkownika i hasła). Technicznie rzecz biorąc, token jest kluczem odwołującym się do zbioru metadanych, które wyglądają tak:

{
  "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"
}

Metadane tokena zawierają rzeczywisty ciąg tokena dostępu, informacje o wygaśnięciu, identyfikację aplikacji dewelopera, dewelopera i produktów powiązanych z tokenem. Zwróć też uwagę, że metadane zawierają też „zakres”.

W jaki sposób token uzyskuje swój zakres?

Należy pamiętać, że do każdej usługi w aplikacji dewelopera można przypisać 0 lub więcej zakresów. Zakresy można przypisać podczas tworzenia usługi lub dodać je później. Mają postać listy nazw i są uwzględniane w „metadanych” powiązanych z każdą usługą.

Gdy tworzysz aplikację dewelopera i dodajesz do niej produkty, Edge sprawdza wszystkie usługi w aplikacji i tworzy listę wszystkich ich zakresów (głównych lub globalnych list zakresów aplikacji, które stanowią sumę wszystkich rozpoznawanych zakresów).

Gdy aplikacja kliencka żąda tokena dostępu z Apigee Edge, może opcjonalnie określić zakresy, które chcesz powiązać z tym tokenem. Na przykład poniższe żądanie dotyczy zakresu „A”. Oznacza to, że klient prosi, aby serwer autoryzacji (Edge) wygenerował token dostępu o zakresie „A” (udzielając aplikacji autoryzacji do wywoływania interfejsów API z zakresem „A”). Aplikacja wysyła takie żądanie POST:

curl -i -X POST -H Authorization: Basic Mg12YTk2UkEIyIBCrtro1QpIG -H content-type:application/x-www-form-urlencoded http://myorg-test.apigee.net/oauth/token?grant_type=client_credentials&scope=A

Co się stanie?

Po otrzymaniu tego żądania Edge wie, która aplikacja je wysyła, i wie, którą aplikację dewelopera zarejestrował klient (identyfikator klienta i klucze tajnego klucza klienta są zakodowane w podstawowym nagłówku uwierzytelniania). Uwzględniany jest parametr zapytania scope, dlatego Edge musi zdecydować, czy któreś usługi API powiązane z aplikacją dewelopera mają zakres „A”. Jeśli tak, zostanie wygenerowany token dostępu z zakresem „A”. Można też zauważyć, że parametr zapytania zakresu jest rodzajem filtra. Jeśli aplikacja programisty rozpoznaje zakresy „A, B, X”, a parametr zapytania zawiera wartość „scope=X Y Z”, do tokena zostanie przypisany tylko zakres „X”.

Co się stanie, jeśli klient nie dołączy parametru zakresu? W tym przypadku Edge generuje token obejmujący wszystkie zakresy rozpoznawane przez aplikację dewelopera. Pamiętaj, że domyślnym działaniem jest zwrócenie tokena dostępu, który zawiera sumę wszystkich zakresów dla wszystkich usług zawartych w aplikacji dewelopera.

Jeśli żadna z usług powiązanych z aplikacją dewelopera nie określa zakresów, a token ma zakres, wywołania tego tokena będą nieudane.

Załóżmy, że aplikacja dewelopera rozpoznaje te zakresy: A B C D. To jest główna lista zakresów aplikacji. Jedna usługa w aplikacji może mieć zakresy A i B, a druga – zakres C i D lub dowolną kombinację. Jeśli klient nie określi parametru scope (lub jeśli określa parametr zakresu bez wartości), token otrzyma wszystkie 4 zakresy: A, B, C i D. Token ponownie otrzymuje zestaw zakresów, który stanowi sumę wszystkich zakresów rozpoznawanych przez aplikację dewelopera.

Istnieje jeszcze jeden przypadek, w którym domyślnym działaniem jest zwrócenie tokena dostępu ze wszystkimi rozpoznawanymi zakresami, gdy zasada GenerateAccessToken (zasada Apigee Edge generująca tokeny dostępu) nie określa elementu <Scope>. Oto na przykład zasada GenerateAccessToken, w której jest określona wartość <Scope>. Jeśli brakuje tego elementu <Scope> (lub jeśli jest on obecny, ale jest pusty), wykonywane jest działanie domyślne.

<?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>

Jak egzekwowane są zakresy?

Po pierwsze, pamiętaj, że w Apigee Edge tokeny dostępu są weryfikowane przez zasadę OAuthV2 (zwykle umieszczane na samym początku procesu serwera proxy). Zasada musi mieć podaną operacjęVerifyAccessToken. Przyjrzyjmy się tym zasadom:

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

Zwróć uwagę na element <Scope>. Służy do określania zakresów akceptowanych przez zasadę.

W tym przykładzie zasada zadziała tylko wtedy, gdy token dostępu będzie zawierał zakres „A”. Jeśli ten element <Scope> zostanie pominięty lub nie ma żadnej wartości, zasada ignoruje zakres tokena dostępu.

Dzięki możliwości weryfikowania tokenów dostępu na podstawie zakresu możesz zaprojektować interfejsy API tak, aby wymuszały określone zakresy. Aby to zrobić, zaprojektuj niestandardowe przepływy z przypisanymi do nich zasadami VerificationAccessToken zależnym od zakresu.

Załóżmy, że w przypadku punktu końcowego /resourceA w interfejsie API jest zdefiniowany przepływ:

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

Po uruchomieniu tego procesu (żądanie zawiera w sufiksie ścieżki /resourceA) zasada OAuthV2-VerifyAccessTokenA jest wywoływana natychmiast. Ta zasada sprawdza, czy token dostępu jest prawidłowy, i sprawdza, jakie zakresy obsługuje ten token. Jeśli zasada jest skonfigurowana w sposób opisany poniżej, w przypadku <zakresu>A</Scope> zasada jest skuteczna tylko wtedy, gdy token dostępu ma zakres „A”. W przeciwnym razie zwróci błąd.

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

Mówiąc w skrócie, to deweloperzy API są odpowiedzialni za projektowanie egzekwowania zakresu w swoich interfejsach API. Aby to zrobić, tworzy niestandardowe przepływy obsługujące określone zakresy i dołączają zasadyVerifyAccessToken w celu egzekwowania tych zakresów.

Przykłady kodu

Na koniec przyjrzyjmy się kilku przykładowym wywołaniom interfejsu API, aby zobrazować, jak tokeny otrzymują zakresy i jak egzekwowane są zakresy.

Wielkość domyślna

Załóżmy, że masz aplikację dewelopera z produktami, która obejmuje zakresy tych usług: A, B i C. To wywołanie interfejsu API żąda tokena dostępu, ale nie określa parametru zapytania zakresu.

curl -X POST -H content-type:application/x-www-form-urlencoded http://wwitman-test.apigee.net/scopecheck1/token?grant_type=client_credentials

W tym przypadku wygenerowany token otrzyma zakresy A, B i C (działanie domyślne). Metadane tokena będą wyglądać mniej więcej tak:

{
  "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"
}

Załóżmy teraz, że masz punkt końcowy interfejsu API, który ma zakres „A” (czyli parametr WeryfikacjaAccessToken wymaga zakresu „A”). Oto zasadaVerifyAccessToken:

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

Oto przykładowe wywołanie do punktu końcowego i punkt końcowy, które wymusza zakres A:

curl -X GET -H Authorization: Bearer MveXpj4UYXol38thNoJYIa8fBGlI http://wwitman-test.apigee.net/scopecheck1/resourceA 

To wywołanie GET zakończy się powodzeniem:

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

Działanie jest zakończone sukcesem, ponieważ zasada VerificationAccessToken wywoływana po wywołaniu punktu końcowego wymaga zakresu A, a token dostępu otrzymał zakresy A, B i C. Jest to zachowanie domyślne.

Filtrowanie wielkości liter

Załóżmy, że masz aplikację dewelopera z produktami, które mają zakresy A, B, C i X. Żądasz tokena dostępu i umieszczasz w nim parametr zapytania scope w ten sposób:

curl -i -X POST -H content-type:application/x-www-form-urlencoded 'http://myorg-test.apigee.net/oauth/token?grant_type=client_credentials&scope=A X'

W tym przypadku wygenerowany token otrzyma zakresy A i X, ponieważ oba te zakresy są prawidłowymi zakresami. Pamiętaj, że aplikacja dewelopera rozpoznaje zakresy A, B, C i X. W tym przypadku filtrujesz listę usług API na podstawie tych zakresów. Jeśli usługa ma zakres A lub X, możesz skonfigurować punkty końcowe interfejsu API, które będą wymuszać te zakresy. Jeśli produkt nie ma zakresu A lub X (np. ma B, C i Z), nie można wywoływać interfejsów API, które wymuszają zakresy A lub X, za pomocą tokena.

Gdy wywołujesz interfejs API za pomocą nowego tokena:

curl -X GET -H Authorization: Bearer Rkmqo2UkEIyIBCrtro1QpIG http://wwitman-test.apigee.net/scopecheck1/resourceX

Token dostępu jest weryfikowany przez serwer proxy interfejsu API. Na przykład:

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

Wywołanie GET zostało aktywowane i zwraca odpowiedź. Na przykład:

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

Udało się, ponieważ zasada Weryfikacja AccessToken wymaga zakresu A lub X, a token dostępu zawiera zakresy A i X. Oczywiście, jeśli element <Scope> ma wartość „B”, wywołanie tego nie powiedzie się.

Podsumowanie

Warto wiedzieć, jak Apigee Edge obsługuje zakresy OAuth 2.0. Oto najważniejsze wnioski:

  • Aplikacja dewelopera „rozpoznaje” sumę wszystkich zakresów zdefiniowanych dla wszystkich swoich usług.
  • Gdy aplikacja żąda tokena dostępu, może określić, jakie zakresy chce mieć. To Apigee Edge (serwer autoryzacji) decyduje o tym, które zakresy faktycznie przypisze do tokena dostępu na podstawie (a) żądanych zakresów oraz (b) zakresów rozpoznawanych przez aplikację dewelopera.
  • Jeśli Apigee Edge nie jest skonfigurowane do sprawdzania zakresu (brak elementu <Scope> w zasadzieVerifyAccessToken lub jest on pusty), wywołanie interfejsu API powiedzie się, o ile zakres umieszczony w tokenie dostępu będzie zgodny z jednym z zakresów rozpoznawanych przez zarejestrowaną aplikację dewelopera (jednego z zakresów na „głównym” liście aplikacji).
  • Jeśli z tokenem dostępu nie są powiązane żadne zakresy, odniesie on sukces tylko w sytuacjach, gdy Edge nie weźmie pod uwagę zakresu (brak elementu <Scope> w zasadzie VerificationAccessToken lub jest on pusty).