Browse Source

steam auth

master
gsd 2 years ago
parent
commit
cf86629f4d
  1. 64
      src/main/java/app/controllers/AuthController.java
  2. 123
      src/main/java/app/services/SteamSignIn.java
  3. 23
      src/main/java/app/utils/SaltedCookie.java
  4. 7
      src/main/resources/application.yaml

64
src/main/java/app/controllers/AuthController.java

@ -0,0 +1,64 @@
package app.controllers;
import app.services.SteamSignIn;
import app.utils.SaltedCookie;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
private SteamSignIn steamSignIn;
private SaltedCookie saltedCookie;
@Autowired
public AuthController(SteamSignIn steamSignIn, SaltedCookie saltedCookie){
this.steamSignIn = steamSignIn;
this.saltedCookie = saltedCookie;
}
@GetMapping("login")
public ResponseEntity<Void> Login(){
return steamSignIn.ConstructURLAndRedirect();
}
@GetMapping("logout")
public ResponseEntity<?> Logout(HttpServletResponse response){
Cookie cookie_steam64 = new Cookie("steam64","");
cookie_steam64.setMaxAge(0);
cookie_steam64.setPath("/");
response.addCookie(cookie_steam64);
Cookie cookie_steam64_secured = new Cookie("steam64_secured", "");
cookie_steam64_secured.setMaxAge(0);
cookie_steam64.setPath("/");
response.addCookie(cookie_steam64_secured);
return ResponseEntity.ok().body("logout...");
}
@GetMapping("processlogin")
public ResponseEntity<?> ProcessLogin(@RequestParam Map<String, String> auth_result, HttpServletResponse response){
System.out.println(auth_result);
Long steam64 = steamSignIn.ValidateResults(auth_result);
if(steam64 == null){
return new ResponseEntity<>("returned steam is not valid",HttpStatus.FORBIDDEN);
}
Cookie cookie_steam64 = new Cookie("steam64", steam64.toString());
cookie_steam64.setPath("/");
response.addCookie(cookie_steam64);
Cookie cookie_steam64_secured = new Cookie("steam64_secured", saltedCookie.Hashed(steam64.toString()));
cookie_steam64_secured.setPath("/");
response.addCookie(cookie_steam64_secured);
return ResponseEntity.ok()
.body("login successful");
}
}

123
src/main/java/app/services/SteamSignIn.java

@ -0,0 +1,123 @@
package app.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilder;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Service
public class SteamSignIn {
private final String provider = "https://steamcommunity.com/openid/login?";
@Value("${backend.auth.response_redirect}")
private String responseURL;
private RestTemplate restTemplate;
private final Pattern refinedScripts = Pattern.compile("(?:http)");
private final Pattern validAuth = Pattern.compile("is_valid:true");
private final Pattern Check64ID = Pattern.compile("https://steamcommunity.com/openid/id/(\\d+)");
@Autowired
public void SteamSignIn(){
this.restTemplate = new RestTemplate();
//http://www.chrispad.com/2019/04/disable-encoding-url-using-resttemplate.html
//https://stackoverflow.com/questions/66164546/resttemplate-exchange-fail-on-get-call-but-works-on-curl
//disable double encoding with rest
DefaultUriBuilderFactory defaultUriBuilderFactory = new DefaultUriBuilderFactory();
defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
this.restTemplate.setUriTemplateHandler(defaultUriBuilderFactory);
}
private String encodeValue(String value){
try {
return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException err){
return "";
}
}
private String decodeValue(String value) {
try {
return URLDecoder.decode(value, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException err){
return "";
}
}
public ResponseEntity<Void> ConstructURLAndRedirect(){
Matcher result = refinedScripts.matcher(responseURL);
if (!result.find() || result.group(0).isEmpty()){
responseURL = String.format("http://%s", responseURL);
}
HashMap<String, String> authParameters = new HashMap<>();
authParameters.put("openid.ns", "http://specs.openid.net/auth/2.0");
authParameters.put("openid.mode", "checkid_setup");
authParameters.put("openid.return_to", responseURL);
authParameters.put("openid.realm", responseURL);
authParameters.put("openid.identity", "http://specs.openid.net/auth/2.0/identifier_select");
authParameters.put("openid.claimed_id", "http://specs.openid.net/auth/2.0/identifier_select");
String url = authParameters.keySet().stream()
.map(key -> key + "=" + encodeValue(authParameters.get(key)))
.collect(Collectors.joining("&", provider, ""));
return ResponseEntity.status(HttpStatus.SEE_OTHER).
header("Content-Type", "application/x-www-form-urlencoded").
location(URI.create(url))
.build();
}
//@RequestParam Map<String, String> reqParam
public Long ValidateResults(Map<String, String> results){
Map<String, String> validationArgs = new HashMap<>();
validationArgs.put("openid.assoc_handle", results.get("openid.assoc_handle"));
validationArgs.put("openid.signed", results.get("openid.signed"));
validationArgs.put("openid.sig", results.get("openid.sig"));
validationArgs.put("openid.ns", results.get("openid.ns"));
List<String> signedArgs = Arrays.stream(results.get("openid.signed").split(",")).toList();
for(String item: signedArgs){
String itemArg = String.format("openid.%s", item);
if (!validationArgs.containsKey(results.get(itemArg))) {
validationArgs.put(itemArg, results.get(itemArg));
}
}
validationArgs.put("openid.mode", "check_authentication");
String url = validationArgs.keySet().stream()
.map(key -> key + "=" + encodeValue(validationArgs.get(key)))
.collect(Collectors.joining("&", provider, ""));
String responseData = restTemplate.getForObject(url, String.class);
if (validAuth.matcher(responseData).find()) {
Matcher matcher = Check64ID.matcher(results.get("openid.claimed_id"));
if (!matcher.find() || !matcher.group(1).isEmpty()) {
return Long.valueOf(matcher.group(1));
} else {
return null;
}
} else {
return null;
}
}
}

23
src/main/java/app/utils/SaltedCookie.java

@ -0,0 +1,23 @@
package app.utils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
@Component
public class SaltedCookie {
@Value("${backend.auth.salt}")
private String salt;
public String Hashed(String value) {
return DigestUtils.md5DigestAsHex(String.format("%s+%s", value, salt).getBytes());
}
public boolean Validate(String value, String hashed_value) {
return Hashed(value).equals(hashed_value);
}
public boolean Validate(Long value, String hashed_value) {
return Validate(value.toString(), hashed_value);
}
}

7
src/main/resources/application.yaml

@ -29,7 +29,12 @@ backend:
unique_server: false
ban_count: false
a2s: false
countries: true
countries: false
auth:
salt: ${AUTH_SALT}
steam_api_key: ${STEAM_WEBAPI_KEY}
response_redirect: ${AUTH_REDIRECT}
logging:
level:
com.ibasco.agql.core.util.*: OFF
Loading…
Cancel
Save