Spring Security OAuth2 - Enkel tilbagekaldelse af token (ved hjælp af Spring Security OAuth legacy stack)

1. Oversigt

I denne hurtige vejledning illustrerer vi, hvordan vi kan tilbagekalde tokens, der er tildelt af en OAuth-autorisationsserver implementeret med Forårssikkerhed.

Når en bruger logger ud, fjernes deres token ikke med det samme fra tokenbutikken. i stedet forbliver den gyldig, indtil den udløber alene.

Og så vil tilbagekaldelse af et token betyde at fjerne dette token fra tokenbutikken. Vi dækker standardtokenimplementeringen i rammen, ikke JWT-tokens.

Bemærk: denne artikel bruger Spring OAuth-arvsprojektet.

2. Den TokenStore

Lad os først oprette tokenbutikken; vi bruger en JdbcTokenStoresammen med den ledsagende datakilde:

@Bean offentlig TokenStore tokenStore () {returner ny JdbcTokenStore (dataSource ()); } @Bean public DataSource dataSource () {DriverManagerDataSource dataSource = ny DriverManagerDataSource (); dataSource.setDriverClassName (env.getProperty ("jdbc.driverClassName")); dataSource.setUrl (env.getProperty ("jdbc.url")); dataSource.setUsername (env.getProperty ("jdbc.user")); dataSource.setPassword (env.getProperty ("jdbc.pass")); returnere datakilde; }

3. Den DefaultTokenServices Bønne

Klassen, der håndterer alle tokens, er DefaultTokenServices - og skal defineres som en bønne i vores konfiguration:

@Bean @Primary offentlig DefaultTokenServices tokenServices () {DefaultTokenServices defaultTokenServices = ny DefaultTokenServices (); defaultTokenServices.setTokenStore (tokenStore ()); defaultTokenServices.setSupportRefreshToken (true); returner defaultTokenServices; }

4. Visning af listen over tokens

Til admin-formål skal vi også oprette en måde at se de aktuelt gyldige tokens på.

Vi får adgang til TokenStore i en controller og hente de aktuelt gemte tokens til et specificeret klient-id:

@Resource (name = "tokenStore") TokenStore tokenStore; @RequestMapping (method = RequestMethod.GET, value = "/ tokens") @ResponseBody public List getTokens () {List tokenValues ​​= new ArrayList (); Samlingstoken = tokenStore.findTokensByClientId ("sampleClientId"); if (tokens! = null) {for (OAuth2AccessToken token: tokens) {tokenValues.add (token.getValue ()); }} returner tokenValues; }

5. Tilbagekaldelse af et adgangstoken

For at ugyldiggøre et token bruger vi revokeToken () API fra ConsumerTokenServices grænseflade:

@Resource (name = "tokenServices") ConsumerTokenServices tokenServices; @RequestMapping (metode = RequestMethod.POST, værdi = "/tokens/revoke/{tokenId:.*}") @ResponseBody offentlig String revokeToken (@PathVariable String tokenId) {tokenServices.revokeToken (tokenId); return tokenId; }

Naturligvis er dette en meget følsom operation, så vi skal enten kun bruge den internt, eller vi skal være meget forsigtige med at udsætte den med den rette sikkerhed på plads.

6. Frontend

For front-end af vores eksempel viser vi listen over gyldige tokens, det token, der i øjeblikket bruges af den indloggede bruger, der foretager tilbagekaldelsesanmodningen, og et felt, hvor brugeren kan indtaste det token, de ønsker at tilbagekalde:

$ scope.revokeToken = $ ressource ("// localhost: 8082 / spring-security-oauth-resource / tokens / revoke /: tokenId", {tokenId: '@ tokenId'}); $ scope.tokens = $ ressource ("// localhost: 8082 / spring-security-oauth-resource / tokens"); $ scope.getTokens = funktion () {$ scope.tokenList = $ scope.tokens.query (); } $ scope.revokeAccessToken = funktion () {if ($ scope.tokenToRevoke && $ scope.tokenToRevoke.length! = 0) {$ scope.revokeToken.save ({tokenId: $ scope.tokenToRevoke}); $ rootScope.message = "Token:" + $ scope.tokenToRevoke + "blev tilbagekaldt!"; $ scope.tokenToRevoke = ""; }}

Hvis en bruger forsøger at bruge et tilbagekaldt token igen, modtager de en 'ugyldig token' -fejl med statuskode 401.

7. Tilbagekaldelse af opfriskningstokenet

Opdateringstokenet kan bruges til at få et nyt adgangstoken. Hver gang et adgangstoken tilbagekaldes, annulleres opdateringstokenet, der blev modtaget med det.

Hvis vi også vil annullere selve opdateringstokenet, kan vi bruge metoden removeRefreshToken () af klassen JdbcTokenStore, som fjerner opdateringstoken fra butikken:

@RequestMapping (metode = RequestMethod.POST, værdi = "/tokens/revokeRefreshToken/{tokenId:.*}") @ResponseBody public String revokeRefreshToken (@PathVariable String tokenId) {if (tokenStore instans af JdbcTokenStore) ((JokeBoreStore)) .removeRefreshToken (tokenId); } returner tokenId; }

For at teste, at opdateringstokenet ikke længere er gyldigt efter at være tilbagekaldt, skriver vi følgende test, hvor vi får adgangstoken, opdaterer det, fjerner opdateringstoken og forsøger at opdatere det igen.

Vi ser, at vi efter tilbagekaldelse modtager svarfejlen: "ugyldigt opdateringstoken":

offentlig klasse TokenRevocationLiveTest {private String refreshToken; private String obtainAccessToken (String clientId, String brugernavn, String password) {Map params = new HashMap (); params.put ("grant_type", "password"); params.put ("client_id", clientId); params.put ("brugernavn", brugernavn); params.put ("adgangskode", adgangskode); Svarrespons = RestAssured.given (). Auth (). præemptive (). basic (clientId, "secret"). og (). med (). params (params). når (). post ("// localhost: 8081 / spring-security-oauth-server / oauth / token"); refreshToken = respons.jsonPath (). getString ("refresh_token"); returnere respons.jsonPath (). getString ("access_token"); } privat String obtainRefreshToken (String clientId) {Map params = new HashMap (); params.put ("grant_type", "refresh_token"); params.put ("client_id", clientId); params.put ("refresh_token", refreshToken); Svarrespons = RestAssured.given (). Auth (). Forebyggende (). Basic (clientId, "hemmelig"). Og (). Med (). Params (params). Når (). Post ("// localhost: 8081 / spring-security-oauth-server / oauth / token "); returnere respons.jsonPath (). getString ("access_token"); } privat ugyldighed authorizeClient (String clientId) {Map params = new HashMap (); params.put ("respons_type", "kode"); params.put ("client_id", clientId); params.put ("scope", "read, skriv"); Svarrespons = RestAssured.given (). Auth (). Præemptive () .basic (clientId, "secret"). Og (). Med (). Params (params). når (). post ("// localhost: 8081 / spring-security-oauth-server / oauth / authorize"); } @Test offentlig ugyldighed givetUser_whenRevokeRefreshToken_thenRefreshTokenInvalidError () {String accessToken1 = obtainAccessToken ("fooClientIdPassword", "john", "123"); Streng accessToken2 = obtainAccessToken ("fooClientIdPassword", "tom", "111"); authorizeClient ("fooClientIdPassword"); Streng accessToken3 = fåRefreshToken ("fooClientIdPassword"); authorizeClient ("fooClientIdPassword"); Svar refreshTokenResponse = RestAssured.given (). header ("Authorization", "Bearer" + accessToken3) .get ("// localhost: 8082 / spring-security-oauth-resource / tokens"); assertEquals (200, refreshTokenResponse.getStatusCode ()); Svar revokeRefreshTokenResponse = RestAssured.given () .header ("Authorization", "Bearer" + accessToken1) .post ("// localhost: 8082 / spring-security-oauth-resource / tokens / revokeRefreshToken /" + refreshToken); assertEquals (200, revokeRefreshTokenResponse.getStatusCode ()); Streng accessToken4 = fåRefreshToken ("fooClientIdPassword"); authorizeClient ("fooClientIdPassword"); Svar refreshTokenResponse2 = RestAssured.given () .header ("Authorization", "Bearer" + accessToken4) .get ("// localhost: 8082 / spring-security-oauth-resource / tokens"); assertEquals (401, refreshTokenResponse2.getStatusCode ()); }}

8. Konklusion

I denne vejledning har vi demonstreret, hvordan man tilbagekalder et OAuth-adgangstoken og et Oauth-opdateringstoken.

Implementeringen af ​​denne vejledning kan findes i GitHub-projektet.


$config[zx-auto] not found$config[zx-overlay] not found