Log uit in een met OAuth beveiligde applicatie

1. Overzicht

In deze korte tutorial laten we zien hoe we dat kunnen uitlogfunctionaliteit toevoegen aan een OAuth Spring Security-applicatie.

We zullen een aantal manieren zien om dit te doen. Eerst zullen we zien hoe we onze Keycloak-gebruiker kunnen uitloggen bij de OAuth-applicatie, zoals beschreven in Een REST API maken met OAuth2, en vervolgens de Zuul-proxy gebruiken die we eerder zagen.

We gebruiken de OAuth-stack in Spring Security 5. Als u de verouderde OAuth-stack van Spring Security wilt gebruiken, bekijk dan dit vorige artikel: Uitloggen in een OAuth-beveiligde applicatie (met behulp van de legacy-stack).

2. Uitloggen met behulp van front-end applicatie

Aangezien de toegangstokens worden beheerd door de autorisatieserver, moeten ze op dit niveau ongeldig worden gemaakt. De exacte stappen om dit te doen zullen enigszins verschillen, afhankelijk van de autorisatieserver die u gebruikt.

In ons voorbeeld kunnen we, volgens de Keycloak-documentatie, om rechtstreeks uit een browsertoepassing uit te loggen de browser omleiden naar // auth-server / auth / realms / {realm-name} / protocol / openid-connect / logout? redirect_uri = encodedRedirectUri.

Naast het verzenden van de omleidings-URI, moeten we ook een id_token_hint naar het uitlog-eindpunt van Keycloak. Dit zou het gecodeerde id_token waarde.

Laten we ons herinneren hoe we het toegangstoken, slaan we op dezelfde manier de id_token ook:

saveToken (token) {var expireDate = nieuwe datum (). getTime () + (1000 * token.expires_in); Cookie.set ("access_token", token.access_token, expireDate); Cookie.set ("id_token", token.id_token, expireDate); this._router.navigate (['/']); } 

Belangrijk is dat we, om het ID-token in de responspayload van de autorisatieserver te verkrijgen, moeten opnemen openid in de bereikparameter.

Laten we nu het uitlogproces in actie zien.

We zullen onze functie aanpassen uitloggen in App Service:

logout () {let token = Cookie.get ('id_token'); Cookie.delete ('access_token'); Cookie.delete ('id_token'); let logoutURL = "// localhost: 8083 / auth / realms / baeldung / protocol / openid-connect / logout? id_token_hint =" + token + "& post_logout_redirect_uri =" + this.redirectUri; window.location.href = logoutURL; }

Afgezien van de omleiding, we moeten ook de toegangs- en ID-tokens weggooien die we hadden verkregen van de autorisatieserver.

Daarom hebben we in de bovenstaande code eerst de tokens verwijderd en vervolgens de browser omgeleid naar Keycloak's uitloggen API.

Met name hebben we de omleidings-URI doorgegeven als // localhost: 8089 / - degene die we in de hele applicatie gebruiken - dus we komen op de bestemmingspagina terecht nadat we zijn uitgelogd.

Het verwijderen van toegangs-, ID- en vernieuwingstokens die overeenkomen met de huidige sessie, wordt uitgevoerd aan het einde van de autorisatieserver. Onze browsertoepassing had in dit geval het Refresh Token helemaal niet opgeslagen.

3. Uitloggen met Zuul Proxy

In een eerder artikel over het afhandelen van het vernieuwingstoken hebben we onze applicatie zo ingesteld dat het toegangstoken kan worden vernieuwd met behulp van een vernieuwingstoken. Deze implementatie maakt gebruik van een Zuul-proxy met aangepaste filters.

Hier zullen we zien hoe u de uitlogfunctionaliteit aan het bovenstaande kunt toevoegen.

Deze keer gebruiken we een andere Keycloak API om een ​​gebruiker uit te loggen. We zullen POST aanroepen op de uitloggen eindpunt om een ​​sessie af te melden via een niet-browseraanroep, in plaats van de URL-omleiding die we in de vorige sectie hebben gebruikt.

3.1. Definieer een route voor uitloggen

Laten we om te beginnen nog een route toevoegen aan de proxy in onze application.yml:

zuul: routes: // ... auth / refresh / revoke: path: / auth / refresh / revoke / ** sensitiveHeaders: url: // localhost: 8083 / auth / realms / baeldung / protocol / openid-connect / logout / / auth / refresh route

In feite hebben we een subroute toegevoegd aan de reeds bestaande auth / vernieuwen. Het is belangrijk dat we de subroute vóór de hoofdroute toevoegen, anders zal Zuul altijd de URL van de hoofdroute in kaart brengen.

We hebben een subroute toegevoegd in plaats van een hoofdroute om alleen toegang te hebben tot de HTTP refreshToken cookie, die was ingesteld om een ​​zeer beperkt pad te hebben als / auth / vernieuwen (en zijn subpaden). In de volgende sectie zullen we zien waarom we de cookie nodig hebben.

3.2. POST naar autorisatieserver /uitloggen

Laten we nu het CustomPreZuulFilter implementatie om de / auth / refresh / revoke URL en voeg de benodigde informatie toe die moet worden doorgegeven aan de autorisatieserver.

De formulierparameters die nodig zijn om uit te loggen, zijn vergelijkbaar met die van het Refresh Token-verzoek, behalve dat er geen grant_type:

@Component public class CustomPostZuulFilter breidt ZuulFilter uit {// ... @Override public Object run () {// ... if (requestURI.contains ("auth / refresh / revoke")) {String cookieValue = extractCookie (req, " refreshToken "); String formParams = String.format ("client_id =% s & client_secret =% s & refresh_token =% s", CLIENT_ID, CLIENT_SECRET, cookieValue); bytes = formParams.getBytes ("UTF-8"); } // ...}}

Hier hebben we eenvoudig het refreshToken cookie en verzonden in het vereiste formParams.

3.3. Verwijder het vernieuwingstoken

Bij het intrekken van het toegangstoken met behulp van de uitloggen omleiding zoals we eerder zagen, wordt het bijbehorende vernieuwingstoken ook ongeldig gemaakt door de autorisatieserver.

In dit geval is het httpAlleen cookie blijft ingesteld op de klant. Aangezien we het niet via JavaScript kunnen verwijderen, moeten we het van de server verwijderen.

Laten we daarvoor toevoegen aan de CustomPostZuulFilter implementatie die de / auth / refresh / revoke URL zodat het zal Verwijder de refreshToken koekje wanneer u deze URL tegenkomt:

@Component public class CustomPostZuulFilter breidt ZuulFilter uit {// ... @Override public Object run () {// ... String requestMethod = ctx.getRequest (). GetMethod (); if (requestURI.contains ("auth / refresh / revoke")) {Cookie cookie = nieuwe Cookie ("refreshToken", ""); cookie.setMaxAge (0); ctx.getResponse (). addCookie (cookie); } // ...}}

3.4. Verwijder het toegangstoken uit de Angular-client

Naast het intrekken van het vernieuwingstoken, is het toegangstoken cookie moet ook aan de clientzijde worden verwijderd.

Laten we een methode toevoegen aan onze Angular-controller die de toegangstoken cookie en roept het / auth / refresh / revoke POST-toewijzing:

logout () {let headers = new HttpHeaders ({'Content-type': 'application / x-www-form-urlencoded; charset = utf-8'}); this._http.post ('auth / refresh / revoke', {}, {headers: headers}) .subscribe (data => {Cookie.delete ('access_token'); window.location.href = '// localhost: 8089 / ';}, err => alert (' Kon niet uitloggen ')); }

Deze functie wordt aangeroepen wanneer u op de knop Afmelden klikt:

Uitloggen

4. Conclusie

In deze snelle, maar diepgaande zelfstudie hebben we laten zien hoe we een gebruiker kunnen uitloggen bij een OAuth beveiligde applicatie en maak de tokens van die gebruiker ongeldig.

De volledige broncode van de voorbeelden is te vinden op GitHub.