diff options
| author | Linnea Gräf <nea@nea.moe> | 2025-10-12 20:05:48 +0200 |
|---|---|---|
| committer | Linnea Gräf <nea@nea.moe> | 2025-10-12 20:21:32 +0200 |
| commit | 60dfd15a88242893a7a422b82604d25171809f77 (patch) | |
| tree | eeab8a964e8f449c71083f7c6da6816350fb964d /src/main/java/moe/nea/prickly/util/OAuthUtil.java | |
| parent | abc83ee7180e2ea4c5d65689dca48bfe88023862 (diff) | |
| download | prickly-60dfd15a88242893a7a422b82604d25171809f77.tar.gz prickly-60dfd15a88242893a7a422b82604d25171809f77.tar.bz2 prickly-60dfd15a88242893a7a422b82604d25171809f77.zip | |
feat: add basic authorize endpoint
Diffstat (limited to 'src/main/java/moe/nea/prickly/util/OAuthUtil.java')
| -rw-r--r-- | src/main/java/moe/nea/prickly/util/OAuthUtil.java | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/main/java/moe/nea/prickly/util/OAuthUtil.java b/src/main/java/moe/nea/prickly/util/OAuthUtil.java new file mode 100644 index 0000000..ec3b7fd --- /dev/null +++ b/src/main/java/moe/nea/prickly/util/OAuthUtil.java @@ -0,0 +1,54 @@ +/* (C) 2025 Linnea Gräf - Licensed to everyone under the BSD 3 Clause License */ +package moe.nea.prickly.util; + +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import java.net.URI; +import java.util.List; +import java.util.Objects; +import org.jspecify.annotations.Nullable; + +public class OAuthUtil { + private static final Splitter SCOPE_SPLITTER = + Splitter.on(' ').omitEmptyStrings().trimResults(); + + public static List<String> parseScopes(@Nullable String scope) { + if (scope == null) return List.of(); + return SCOPE_SPLITTER.splitToList(scope); + } + + public static URI verifyRedirectUrl(@Nullable String actualRedirectUri, String expectedRedirectUri) { + Objects.requireNonNull(expectedRedirectUri, "expected redirect uri is null"); + if (actualRedirectUri == null) return verifyRedirectUrl(expectedRedirectUri, expectedRedirectUri); + + var expected = URI.create(expectedRedirectUri); + var actual = URI.create(actualRedirectUri).normalize(); + Preconditions.checkArgument(actual.isAbsolute(), "redirect URI must be absolute"); + Preconditions.checkArgument(actual.getFragment() == null, "redirect URI must not have a fragment"); + Preconditions.checkArgument( + Objects.equals(actual.getScheme(), expected.getScheme()), + "scheme differs from registered redirect URI"); + Preconditions.checkArgument( + Objects.equals(actual.getAuthority(), expected.getAuthority()), + "origin differs from registered redirect URI"); + Preconditions.checkArgument(actual.getUserInfo() == null, "redirect URI must not have a user info"); + Preconditions.checkArgument( + expected.getPath() == null || actual.getPath().startsWith(expected.getPath()), + "redirect URI must be a subpath of registered redirect URI"); + return actual; + } + + public static ResponseType parseResponseType(@Nullable String responseType) { + return switch (responseType) { + case "code" -> ResponseType.CODE; + case "token" -> ResponseType.TOKEN; + case null -> throw new IllegalArgumentException("missing response_type"); + default -> throw new IllegalArgumentException("invalid response_type " + responseType); + }; + } + + public enum ResponseType { + TOKEN, + CODE + } +} |
