Skip to content

Commit

Permalink
ARC-1222: Test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasrichner-oviva committed Feb 4, 2024
1 parent ebb24fc commit ecad68b
Show file tree
Hide file tree
Showing 13 changed files with 661 additions and 80 deletions.
4 changes: 2 additions & 2 deletions oidc-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@
<artifactId>resteasy-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<groupId>com.fasterxml.jackson.jakarta.rs</groupId>
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
</dependency>

<!-- BEGIN logging-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.oviva.gesundheitsid.relyingparty.svc.InMemorySessionRepo;
import com.oviva.gesundheitsid.relyingparty.svc.KeyStore;
import com.oviva.gesundheitsid.relyingparty.svc.TokenIssuerImpl;
import com.oviva.gesundheitsid.relyingparty.util.Strings;
import com.oviva.gesundheitsid.relyingparty.ws.App;
import jakarta.ws.rs.SeBootstrap;
import jakarta.ws.rs.SeBootstrap.Configuration;
Expand Down Expand Up @@ -38,7 +39,7 @@ public static void main(String[] args) throws ExecutionException, InterruptedExc
main.run(new EnvConfigProvider("OIDC_SERVER", System::getenv));
}

private void run(ConfigProvider configProvider) throws ExecutionException, InterruptedException {
public void run(ConfigProvider configProvider) throws ExecutionException, InterruptedException {
logger.atInfo().log("\n" + BANNER);

var baseUri = URI.create("https://t.oviva.io");
Expand All @@ -57,10 +58,11 @@ private void run(ConfigProvider configProvider) throws ExecutionException, Inter
// + port)),
supportedResponseTypes,
validRedirectUris // TODO: hardcoded :)
// configProvider.get("redirect_uris").stream()
// .flatMap(this::mustParseCommaList)
// .map(URI::create)
// .toList()

// configProvider.get("redirect_uris").stream()
// .flatMap(Strings::mustParseCommaList)
// .map(URI::create)
// .toList()
);

var keyStore = new KeyStore();
Expand All @@ -80,20 +82,4 @@ private void run(ConfigProvider configProvider) throws ExecutionException, Inter
// wait forever
Thread.currentThread().join();
}

private Stream<String> mustParseCommaList(String value) {
if (value == null || value.isBlank()) {
return Stream.empty();
}

return Arrays.stream(value.split(",")).map(this::trimmed).filter(Objects::nonNull);
}

private String trimmed(String value) {
if (value == null || value.isBlank()) {
return null;
}

return value.trim();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public interface TokenIssuer {

Code issueCode(Session session);

Token redeem(@NonNull String code);
Token redeem(@NonNull String code, String redirectUri, String clientId);

record Code(
String code,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
import com.oviva.gesundheitsid.relyingparty.util.IdGenerator;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.Clock;
import java.time.Duration;
import java.util.Date;
import java.util.UUID;
import org.apache.commons.codec.cli.Digest;

public class TokenIssuerImpl implements TokenIssuer {

Expand Down Expand Up @@ -48,13 +51,14 @@ public Code issueCode(Session session) {
}

@Override
public Token redeem(@NonNull String code) {
public Token redeem(@NonNull String code, String redirectUri, String clientId) {

var redeemed = codeRepo.remove(code).orElse(null);
if (redeemed == null) {
return null;
}

if (redeemed.expiresAt().isBefore(clock.instant())) {
if (!validateCode(redeemed, redirectUri, clientId)) {
return null;
}

Expand All @@ -65,6 +69,23 @@ public Token redeem(@NonNull String code) {
accessTokenTtl.getSeconds());
}

private boolean validateCode(Code code, String redirectUri, String clientId) {

if (code.expiresAt().isBefore(clock.instant())) {
return false;
}

if (redirectUri == null || clientId == null) {
return false;
}

if (!code.redirectUri().toString().equals(redirectUri)) {
return false;
}

return code.clientId().equals(clientId);
}

private String issueIdToken(String audience, String nonce) {
try {
var jwk = keyStore.signingKey();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.oviva.gesundheitsid.relyingparty.util;

import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Stream;

public class Strings {

public static Stream<String> mustParseCommaList(String value) {
if (value == null || value.isBlank()) {
return Stream.empty();
}

return Arrays.stream(value.split(",")).map(Strings::trimmed).filter(Objects::nonNull);
}

public static String trimmed(String value) {
if (value == null || value.isBlank()) {
return null;
}

return value.trim();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public Set<Object> getSingletons() {

return Set.of(
new OpenIdEndpoint(config, sessionRepo, tokenIssuer, keyStore),
new RequestLogFilter(),
new JacksonJsonProvider(configureObjectMapper()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ public Response auth(
.build();
}

if (!"https".equals(parsedRedirect.getScheme())) {
// TODO nice form
return Response.status(Status.BAD_REQUEST)
.entity("not https 'redirect_uri': %s".formatted(parsedRedirect))
.build();
}

if (!config.validRedirectUris().contains(parsedRedirect)) {
// TODO nice form
return Response.status(Status.BAD_REQUEST)
Expand Down Expand Up @@ -204,10 +211,16 @@ public Response token(
@FormParam("client_id") String clientId) {

if (!"authorization_code".equals(grantType)) {
return Response.serverError().build(); // TODO
return Response.status(Status.BAD_REQUEST).entity("bad 'grant_type': " + grantType).build();
}

var redeemed = tokenIssuer.redeem(code, redirectUri, clientId);
if (redeemed == null) {
return Response.status(Status.BAD_REQUEST).entity("invalid code").build();
}

var redeemed = tokenIssuer.redeem(code);
var cacheControl = new CacheControl();
cacheControl.setNoStore(true);

return Response.ok(
new TokenResponse(
Expand All @@ -216,6 +229,7 @@ public Response token(
null,
(int) redeemed.expiresInSeconds(),
redeemed.idToken()))
.cacheControl(cacheControl)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static Response redirectWithError(
addNonBlankQueryParam(builder, "error_description", description);
addNonBlankQueryParam(builder, "state", state);

return Response.seeOther(redirectUri).build();
return Response.seeOther(builder.build()).build();
}

private static void addNonBlankQueryParam(UriBuilder builder, String name, String value) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.oviva.gesundheitsid.relyingparty;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;

import com.oviva.gesundheitsid.relyingparty.cfg.ConfigProvider;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.Test;

class MainTest {

@Test
void test() throws ExecutionException, InterruptedException {
var sut = new Main();

var configProvider = mock(ConfigProvider.class);

sut.run(configProvider);
}
}
Loading

0 comments on commit ecad68b

Please sign in to comment.