forked from WebGoat/WebGoat
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Last assignment for JWT tokens finished
- Loading branch information
Showing
10 changed files
with
394 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,15 @@ | ||
<configuration /> | ||
<configuration /> | ||
|
||
<!-- | ||
Enable below if you want to debug a unit test and see why the controller fails the configuration above is there | ||
to keep the Travis build going otherwise it fails with too much logging. | ||
//TODO we should use a different Spring profile for Travis | ||
--> | ||
|
||
<!-- | ||
<configuration> | ||
<include resource="org/springframework/boot/logging/logback/base.xml"/> | ||
<logger name="org.springframework.web" level="DEBUG"/> | ||
</configuration> | ||
--> |
109 changes: 109 additions & 0 deletions
109
webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTRefreshEndpoint.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package org.owasp.webgoat.plugin; | ||
|
||
import com.google.common.collect.Lists; | ||
import com.google.common.collect.Maps; | ||
import io.jsonwebtoken.*; | ||
import org.apache.commons.lang3.RandomStringUtils; | ||
import org.owasp.webgoat.assignments.AssignmentEndpoint; | ||
import org.owasp.webgoat.assignments.AssignmentHints; | ||
import org.owasp.webgoat.assignments.AssignmentPath; | ||
import org.owasp.webgoat.assignments.AttackResult; | ||
import org.owasp.webgoat.session.WebSession; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestHeader; | ||
import org.springframework.web.bind.annotation.ResponseBody; | ||
|
||
import java.util.Date; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
/** | ||
* @author nbaars | ||
* @since 4/23/17. | ||
*/ | ||
@AssignmentPath("/JWT/refresh/") | ||
@AssignmentHints({"jwt-refresh-hint1", "jwt-refresh-hint2", "jwt-refresh-hint3", "jwt-refresh-hint4"}) | ||
public class JWTRefreshEndpoint extends AssignmentEndpoint { | ||
|
||
public static final String PASSWORD = "bm5nhSkxCXZkKRy4"; | ||
private static final String JWT_PASSWORD = "bm5n3SkxCX4kKRy4"; | ||
private static final List<String> validRefreshTokens = Lists.newArrayList(); | ||
|
||
@PostMapping(value = "login", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) | ||
public @ResponseBody | ||
ResponseEntity follow(@RequestBody Map<String, Object> json) { | ||
String user = (String) json.get("user"); | ||
String password = (String) json.get("password"); | ||
|
||
if ("Jerry".equals(user) && PASSWORD.equals(password)) { | ||
return ResponseEntity.ok(createNewTokens(user)); | ||
} | ||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); | ||
} | ||
|
||
private Map<String, Object> createNewTokens(String user) { | ||
Map<String, Object> claims = Maps.newHashMap(); | ||
claims.put("admin", "false"); | ||
claims.put("user", user); | ||
String token = Jwts.builder() | ||
.setIssuedAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toDays(10))) | ||
.setClaims(claims) | ||
.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, JWT_PASSWORD) | ||
.compact(); | ||
Map<String, Object> tokenJson = Maps.newHashMap(); | ||
String refreshToken = RandomStringUtils.randomAlphabetic(20); | ||
validRefreshTokens.add(refreshToken); | ||
tokenJson.put("access_token", token); | ||
tokenJson.put("refresh_token", refreshToken); | ||
return tokenJson; | ||
} | ||
|
||
@PostMapping("checkout") | ||
public @ResponseBody | ||
AttackResult checkout(@RequestHeader("Authorization") String token) { | ||
try { | ||
Jwt jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(token.replace("Bearer ", "")); | ||
Claims claims = (Claims) jwt.getBody(); | ||
String user = (String) claims.get("user"); | ||
if ("Tom".equals(user)) { | ||
return trackProgress(success().build()); | ||
} | ||
return trackProgress(failed().feedback("jwt-refresh-not-tom").feedbackArgs(user).build()); | ||
} catch (ExpiredJwtException e) { | ||
return trackProgress(failed().output(e.getMessage()).build()); | ||
} catch (JwtException e) { | ||
return trackProgress(failed().feedback("jwt-invalid-token").build()); | ||
} | ||
} | ||
|
||
@PostMapping("newToken") | ||
public @ResponseBody | ||
ResponseEntity newToken(@RequestHeader("Authorization") String token, @RequestBody Map<String, Object> json) { | ||
String user; | ||
String refreshToken; | ||
try { | ||
Jwt<Header, Claims> jwt = Jwts.parser().setSigningKey(JWT_PASSWORD).parse(token.replace("Bearer ", "")); | ||
user = (String) jwt.getBody().get("user"); | ||
refreshToken = (String) json.get("refresh_token"); | ||
} catch (ExpiredJwtException e) { | ||
user = (String) e.getClaims().get("user"); | ||
refreshToken = (String) json.get("refresh_token"); | ||
} | ||
|
||
if (user == null || refreshToken == null) { | ||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); | ||
} else if (validRefreshTokens.contains(refreshToken)) { | ||
validRefreshTokens.remove(refreshToken); | ||
return ResponseEntity.ok(createNewTokens(user)); | ||
} else { | ||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
|
||
205.167.170.15 - - [28/Jan/2016:21:28:01 +0100] "GET /statuses/605086114483826688/favorite?authenticity_token=264c8bf11e0212227c001b77543c3519 HTTP/1.1" 404 242 "-" "Go-http-client/1.1" "-" | ||
205.167.170.15 - - [28/Jan/2016:21:28:01 +0100] "GET /images/phocagallery/almhuette/thumbs/phoca_thumb_l_zimmer.jpg HTTP/1.1" 200 12783 "-" "Go-http-client/1.1" "-" | ||
205.167.170.15 - - [28/Jan/2016:21:28:01 +0100] "GET /signup HTTP/1.1" 404 212 "-" "Go-http-client/1.1" "-" | ||
205.167.170.15 - - [28/Jan/2016:21:28:01 +0100] "GET /vsmartseo/status/605086114483826688/actions HTTP/1.1" 404 249 "-" "Go-http-client/1.1" "-" | ||
205.167.170.15 - - [28/Jan/2016:21:28:01 +0100] "GET /vsmartseo?p=s HTTP/1.1" 404 215 "-" "Go-http-client/1.1" "-" | ||
194.201.170.15 - - [28/Jan/2016:21:28:01 +0100] "GET /JWT/refresh/checkout?token=eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1MjYxMzE0MTEsImV4cCI6MTUyNjIxNzgxMSwiYWRtaW4iOiJmYWxzZSIsInVzZXIiOiJUb20ifQ.DCoaq9zQkyDH25EcVWKcdbyVfUL4c9D4jRvsqOqvi9iAd4QuqmKcchfbU8FNzeBNF9tLeFXHZLU4yRkq-bjm7Q HTTP/1.1" 401 242 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0" "-" | ||
194.201.170.15 - - [28/Jan/2016:21:28:01 +0100] "POST /JWT/refresh/moveToCheckout HTTP/1.1" 200 12783 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0" "-" | ||
194.201.170.15 - - [28/Jan/2016:21:28:01 +0100] "POST /JWT/refresh/login HTTP/1.1" 200 212 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0" "-" | ||
194.201.170.15 - - [28/Jan/2016:21:28:01 +0100] "GET /JWT/refresh/addItems HTTP/1.1" 404 249 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0" "-" | ||
195.206.170.15 - - [28/Jan/2016:21:28:01 +0100] "POST /JWT/refresh/moveToCheckout HTTP/1.1" 404 215 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" "-" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
$(document).ready(function () { | ||
login('Jerry'); | ||
}) | ||
|
||
function login(user) { | ||
$.ajax({ | ||
type: 'POST', | ||
url: 'JWT/refresh/login', | ||
contentType: "application/json", | ||
data: JSON.stringify({user: user, password: "bm5nhSkxCXZkKRy4"}) | ||
}).success( | ||
function (response) { | ||
localStorage.setItem('access_token', response['access_token']); | ||
localStorage.setItem('refresh_token', response['refresh_token']); | ||
} | ||
) | ||
} | ||
|
||
//Dev comment: Pass token as header as we had an issue with tokens ending up in the access_log | ||
webgoat.customjs.addBearerToken = function () { | ||
var headers_to_set = {}; | ||
headers_to_set['Authorization'] = 'Bearer ' + localStorage.getItem('access_token'); | ||
return headers_to_set; | ||
} | ||
|
||
//Dev comment: Temporarily disabled from page we need to work out the refresh token flow but for now we can go live with the checkout page | ||
function newToken() { | ||
localStorage.getItem('refreshToken'); | ||
$.ajax({ | ||
headers: { | ||
'Authorization': 'Bearer ' + localStorage.getItem('access_token') | ||
}, | ||
type: 'POST', | ||
url: 'JWT/refresh/newToken', | ||
data: JSON.stringify({refreshToken: localStorage.getItem('refresh_token')}) | ||
}).success( | ||
function () { | ||
localStorage.setItem('access_token', apiToken); | ||
localStorage.setItem('refresh_token', refreshToken); | ||
} | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.