mirror of
https://github.com/ysoftdevs/oauth-playground-server.git
synced 2026-04-29 20:07:22 +02:00
Client and user validation
This commit is contained in:
@@ -1,10 +1,19 @@
|
|||||||
package com.ysoft.geecon;
|
package com.ysoft.geecon;
|
||||||
|
|
||||||
|
import com.ysoft.geecon.dto.OAuthClient;
|
||||||
|
import com.ysoft.geecon.repo.ClientsRepo;
|
||||||
|
import com.ysoft.geecon.repo.UsersRepo;
|
||||||
import io.quarkus.qute.CheckedTemplate;
|
import io.quarkus.qute.CheckedTemplate;
|
||||||
import io.quarkus.qute.TemplateInstance;
|
import io.quarkus.qute.TemplateInstance;
|
||||||
|
import io.quarkus.runtime.util.StringUtil;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
import jakarta.ws.rs.*;
|
import jakarta.ws.rs.*;
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import jakarta.ws.rs.core.UriBuilder;
|
||||||
|
import org.jboss.resteasy.reactive.RestQuery;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Path("/auth")
|
@Path("/auth")
|
||||||
@@ -13,26 +22,128 @@ public class OAuthResource {
|
|||||||
@CheckedTemplate
|
@CheckedTemplate
|
||||||
public static class Templates {
|
public static class Templates {
|
||||||
public static native TemplateInstance login(String loginHint, String error);
|
public static native TemplateInstance login(String loginHint, String error);
|
||||||
|
|
||||||
public static native TemplateInstance consents(List<String> scopes, String error);
|
public static native TemplateInstance consents(List<String> scopes, String error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ClientsRepo clientsRepo;
|
||||||
|
@Inject
|
||||||
|
UsersRepo usersRepo;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.TEXT_HTML)
|
@Produces(MediaType.TEXT_HTML)
|
||||||
public TemplateInstance get(@QueryParam("login_hint") String loginHint) {
|
public TemplateInstance get(AuthParams params) {
|
||||||
return Templates.login(loginHint, "");
|
validateClient(params);
|
||||||
|
|
||||||
|
return Templates.login(params.loginHint, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Produces(MediaType.TEXT_HTML)
|
@Produces(MediaType.TEXT_HTML)
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public TemplateInstance post(@FormParam("username") String username,
|
public Object post(AuthParams params,
|
||||||
@FormParam("password") String password ) {
|
@FormParam("username") String username,
|
||||||
if ("Password1".equals(password)) {
|
@FormParam("password") String password) {
|
||||||
return Templates.consents(List.of("scope1"), "");
|
validateClient(params);
|
||||||
} else {
|
var user = usersRepo.getUser(username);
|
||||||
|
if (user.isEmpty()) {
|
||||||
return Templates.login(username, "invalid_credentials");
|
return Templates.login(username, "invalid_credentials");
|
||||||
}
|
}
|
||||||
|
if (!user.get().validatePassword(password)) {
|
||||||
|
return Templates.login(username, "invalid_credentials");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Response.seeOther(UriBuilder.fromUri(params.redirectUri)
|
||||||
|
.queryParam("code", "randomCode")
|
||||||
|
.queryParam("state", params.state)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private OAuthClient validateClient(AuthParams params) {
|
||||||
|
var client = clientsRepo.getClient(params.clientId)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Not a valid client"));
|
||||||
|
if (!client.validateRedirectUri(params.redirectUri)) {
|
||||||
|
throw new RuntimeException("Invalid redirect URI");
|
||||||
|
}
|
||||||
|
if (StringUtil.isNullOrEmpty(params.state)) {
|
||||||
|
throw new RuntimeException("Invalid state");
|
||||||
|
}
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AuthParams {
|
||||||
|
public enum ResponseType {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestQuery("login_hint")
|
||||||
|
String loginHint;
|
||||||
|
@RestQuery("response_type")
|
||||||
|
ResponseType responseType;
|
||||||
|
@RestQuery("client_id")
|
||||||
|
String clientId;
|
||||||
|
@RestQuery("redirect_uri")
|
||||||
|
String redirectUri;
|
||||||
|
@RestQuery("scope")
|
||||||
|
String scope;
|
||||||
|
@RestQuery("state")
|
||||||
|
String state;
|
||||||
|
|
||||||
|
public String getLoginHint() {
|
||||||
|
return loginHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginHint(String loginHint) {
|
||||||
|
this.loginHint = loginHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseType getResponseType() {
|
||||||
|
return responseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseType(ResponseType responseType) {
|
||||||
|
this.responseType = responseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientId() {
|
||||||
|
return clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientId(String clientId) {
|
||||||
|
this.clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRedirectUri() {
|
||||||
|
return redirectUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedirectUri(String redirectUri) {
|
||||||
|
this.redirectUri = redirectUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScope() {
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScope(String scope) {
|
||||||
|
this.scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(String state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
7
src/main/java/com/ysoft/geecon/dto/OAuthClient.java
Normal file
7
src/main/java/com/ysoft/geecon/dto/OAuthClient.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package com.ysoft.geecon.dto;
|
||||||
|
|
||||||
|
public record OAuthClient(String clientId, String clientSecret, String redirectUri) {
|
||||||
|
public boolean validateRedirectUri(String redirectUri) {
|
||||||
|
return this.redirectUri != null && this.redirectUri.equals(redirectUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/main/java/com/ysoft/geecon/dto/User.java
Normal file
7
src/main/java/com/ysoft/geecon/dto/User.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package com.ysoft.geecon.dto;
|
||||||
|
|
||||||
|
public record User(String login, String password) {
|
||||||
|
public boolean validatePassword(String password) {
|
||||||
|
return this.password != null && this.password.equals(password);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/main/java/com/ysoft/geecon/repo/ClientsRepo.java
Normal file
26
src/main/java/com/ysoft/geecon/repo/ClientsRepo.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package com.ysoft.geecon.repo;
|
||||||
|
|
||||||
|
|
||||||
|
import com.ysoft.geecon.dto.OAuthClient;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ClientsRepo {
|
||||||
|
private final Map<String, OAuthClient> clients = new HashMap<>();
|
||||||
|
|
||||||
|
public ClientsRepo() {
|
||||||
|
register(new OAuthClient("my-public-client", null, "https://localhost:8888/oauth_success"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<OAuthClient> getClient(String clientId) {
|
||||||
|
return Optional.ofNullable(clients.get(clientId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void register(OAuthClient client) {
|
||||||
|
clients.put(client.clientId(), client);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/main/java/com/ysoft/geecon/repo/UsersRepo.java
Normal file
26
src/main/java/com/ysoft/geecon/repo/UsersRepo.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package com.ysoft.geecon.repo;
|
||||||
|
|
||||||
|
import com.ysoft.geecon.dto.OAuthClient;
|
||||||
|
import com.ysoft.geecon.dto.User;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class UsersRepo {
|
||||||
|
private final Map<String, User> users = new HashMap<>();
|
||||||
|
|
||||||
|
public UsersRepo() {
|
||||||
|
register(new User("bob", "Password1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<User> getUser(String username) {
|
||||||
|
return Optional.ofNullable(users.get(username));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void register(User user) {
|
||||||
|
users.put(user.login(), user);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user