Client and user validation

This commit is contained in:
Dusan Jakub
2023-09-13 10:32:52 +02:00
parent ea1cc69f8d
commit 451eccfe00
5 changed files with 185 additions and 8 deletions

View File

@@ -1,10 +1,19 @@
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.TemplateInstance;
import io.quarkus.runtime.util.StringUtil;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
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;
@Path("/auth")
@@ -13,26 +22,128 @@ public class OAuthResource {
@CheckedTemplate
public static class Templates {
public static native TemplateInstance login(String loginHint, String error);
public static native TemplateInstance consents(List<String> scopes, String error);
}
@Inject
ClientsRepo clientsRepo;
@Inject
UsersRepo usersRepo;
@GET
@Produces(MediaType.TEXT_HTML)
public TemplateInstance get(@QueryParam("login_hint") String loginHint) {
return Templates.login(loginHint, "");
public TemplateInstance get(AuthParams params) {
validateClient(params);
return Templates.login(params.loginHint, "");
}
@POST
@Produces(MediaType.TEXT_HTML)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public TemplateInstance post(@FormParam("username") String username,
@FormParam("password") String password ) {
if ("Password1".equals(password)) {
return Templates.consents(List.of("scope1"), "");
} else {
public Object post(AuthParams params,
@FormParam("username") String username,
@FormParam("password") String password) {
validateClient(params);
var user = usersRepo.getUser(username);
if (user.isEmpty()) {
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;
}
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}