Skip to content

Commit 8c1712e

Browse files
committed
Update to Ory Hydra 2.x API
1 parent ab4f350 commit 8c1712e

23 files changed

+798
-266
lines changed

.editorconfig

+5
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ max_line_length=120
66
end_of_line=lf
77
ij_any_line_comment_add_space = true
88
ij_any_line_comment_at_first_column = false
9+
10+
# Disable wildcard imports entirely
11+
ij_kotlin_name_count_to_use_star_import = 2147483647
12+
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
13+
ij_kotlin_packages_to_use_import_on_demand = unset

generate-hydra-model.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#!/bin/sh
22

3-
HYDRA_VERSION="v1.10.2"
3+
HYDRA_VERSION="v2.2.0"
44

55
mkdir -p hydra-generated
66

77
docker run --user 1000 --rm -v "${PWD}/hydra-generated:/local" openapitools/openapi-generator-cli generate \
88
-i "https://raw.githubusercontent.com/ory/hydra/${HYDRA_VERSION}/spec/api.json" \
99
-g kotlin \
10-
--additional-properties modelPackage=sh.ory.hydra.model,serializationLibrary=jackson,swaggerAnnotations=false,hideGenerationTimestamp=true \
10+
--additional-properties modelPackage=sh.ory.hydra.model,serializationLibrary=jackson \
1111
-o /local

src/main/kotlin/com/faforever/userservice/backend/hydra/HydraClient.kt

+18-16
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ import jakarta.ws.rs.QueryParam
1414
import jakarta.ws.rs.core.MediaType
1515
import jakarta.ws.rs.core.Response
1616
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient
17-
import sh.ory.hydra.model.AcceptConsentRequest
18-
import sh.ory.hydra.model.AcceptLoginRequest
19-
import sh.ory.hydra.model.ConsentRequest
17+
import sh.ory.hydra.model.AcceptOAuth2ConsentRequest
18+
import sh.ory.hydra.model.AcceptOAuth2LoginRequest
2019
import sh.ory.hydra.model.GenericError
21-
import sh.ory.hydra.model.LoginRequest
22-
import sh.ory.hydra.model.OAuth2TokenIntrospection
20+
import sh.ory.hydra.model.IntrospectedOAuth2Token
21+
import sh.ory.hydra.model.OAuth2ConsentRequest
22+
import sh.ory.hydra.model.OAuth2LoginRequest
23+
import sh.ory.hydra.model.OAuth2RedirectTo
24+
import sh.ory.hydra.model.RejectOAuth2Request
2325

24-
@Path("/")
26+
@Path("/admin")
2527
@ApplicationScoped
2628
@RegisterRestClient(configKey = "faf-ory-hydra")
2729
interface HydraClient {
@@ -41,42 +43,42 @@ interface HydraClient {
4143
// requesting a handled challenge throws HTTP 410 - Gone
4244
@GET
4345
@Path("/oauth2/auth/requests/login")
44-
fun getLoginRequest(@QueryParam("login_challenge") @NotBlank challenge: String): LoginRequest
46+
fun getLoginRequest(@QueryParam("login_challenge") @NotBlank challenge: String): OAuth2LoginRequest
4547

4648
@GET
4749
@Path("/oauth2/auth/requests/consent")
48-
fun getConsentRequest(@QueryParam("consent_challenge") @NotBlank challenge: String): ConsentRequest
50+
fun getConsentRequest(@QueryParam("consent_challenge") @NotBlank challenge: String): OAuth2ConsentRequest
4951

5052
// accepting login request more than once throws HTTP 409 - Conflict
5153
@PUT
5254
@Path("/oauth2/auth/requests/login/accept")
5355
fun acceptLoginRequest(
5456
@QueryParam("login_challenge") @NotBlank challenge: String,
55-
acceptLoginRequest: AcceptLoginRequest,
56-
): RedirectResponse
57+
acceptLoginRequest: AcceptOAuth2LoginRequest,
58+
): OAuth2RedirectTo
5759

5860
@PUT
5961
@Path("/oauth2/auth/requests/login/reject")
6062
fun rejectLoginRequest(
6163
@QueryParam("login_challenge") @NotBlank challenge: String,
62-
error: GenericError,
63-
): RedirectResponse
64+
payload: RejectOAuth2Request,
65+
): OAuth2RedirectTo
6466

6567
// accepting consent more than once does not cause an error
6668
@PUT
6769
@Path("/oauth2/auth/requests/consent/accept")
6870
fun acceptConsentRequest(
6971
@QueryParam("consent_challenge") @NotBlank challenge: String,
70-
acceptConsentRequest: AcceptConsentRequest,
71-
): RedirectResponse
72+
acceptConsentRequest: AcceptOAuth2ConsentRequest,
73+
): OAuth2RedirectTo
7274

7375
// rejecting consent more than once does not cause an error
7476
@PUT
7577
@Path("/oauth2/auth/requests/consent/reject")
7678
fun rejectConsentRequest(
7779
@QueryParam("consent_challenge") @NotBlank challenge: String,
7880
error: GenericError,
79-
): RedirectResponse
81+
): OAuth2RedirectTo
8082

8183
@DELETE
8284
@Path("/oauth2/auth/sessions/consent")
@@ -92,7 +94,7 @@ interface HydraClient {
9294
fun introspectToken(
9395
@FormParam("token") @NotBlank token: String,
9496
@FormParam("scope") scope: String?,
95-
): OAuth2TokenIntrospection
97+
): IntrospectedOAuth2Token
9698
}
9799

98100
class GoneException(override val message: String?) : RuntimeException(message)

src/main/kotlin/com/faforever/userservice/backend/hydra/HydraService.kt

+20-19
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import jakarta.enterprise.context.ApplicationScoped
99
import jakarta.enterprise.inject.Produces
1010
import jakarta.transaction.Transactional
1111
import org.eclipse.microprofile.rest.client.inject.RestClient
12-
import sh.ory.hydra.model.AcceptConsentRequest
13-
import sh.ory.hydra.model.AcceptLoginRequest
14-
import sh.ory.hydra.model.ConsentRequest
15-
import sh.ory.hydra.model.ConsentRequestSession
12+
import sh.ory.hydra.model.AcceptOAuth2ConsentRequest
13+
import sh.ory.hydra.model.AcceptOAuth2ConsentRequestSession
14+
import sh.ory.hydra.model.AcceptOAuth2LoginRequest
1615
import sh.ory.hydra.model.GenericError
17-
import sh.ory.hydra.model.LoginRequest
16+
import sh.ory.hydra.model.OAuth2ConsentRequest
17+
import sh.ory.hydra.model.OAuth2LoginRequest
18+
import sh.ory.hydra.model.RejectOAuth2Request
1819
import java.net.URI
1920
import java.net.http.HttpClient
2021
import java.net.http.HttpRequest
@@ -53,14 +54,14 @@ class HydraService(
5354
private const val HYDRA_ERROR_TECHNICAL_ERROR = "technical_error"
5455
}
5556

56-
fun getLoginRequest(challenge: String): LoginRequest = hydraClient.getLoginRequest(challenge)
57+
fun getLoginRequest(challenge: String): OAuth2LoginRequest = hydraClient.getLoginRequest(challenge)
5758

5859
@Transactional
5960
fun login(challenge: String, usernameOrEmail: String, password: String, ip: IpAddress): LoginResponse {
60-
val loginRequest = hydraClient.getLoginRequest(challenge)
61-
val lobbyRequested = loginRequest.requestedScope.contains(OAuthScope.LOBBY)
62-
val lobbyDefault =
63-
loginRequest.requestedScope.isEmpty() && loginRequest.client.scope?.contains(OAuthScope.LOBBY) ?: false
61+
val loginRequest = getLoginRequest(challenge)
62+
val lobbyRequested = loginRequest.requestedScope?.contains(OAuthScope.LOBBY) ?: false
63+
val lobbyDefault = loginRequest.requestedScope.isNullOrEmpty() &&
64+
loginRequest.client.scope?.contains(OAuthScope.LOBBY) ?: false
6465
val requiresGameOwnership = lobbyRequested || lobbyDefault
6566

6667
return when (val loginResult = loginService.login(usernameOrEmail, password, ip, requiresGameOwnership)) {
@@ -69,7 +70,7 @@ class HydraService(
6970
is LoginResult.UserNoGameOwnership -> {
7071
rejectLoginRequest(
7172
challenge,
72-
GenericError(
73+
RejectOAuth2Request(
7374
error = HYDRA_ERROR_NO_OWNERSHIP_VERIFICATION,
7475
errorDescription = "You must prove game ownership to play",
7576
statusCode = 403,
@@ -83,7 +84,7 @@ class HydraService(
8384
"You are banned from FAF ${loginResult.expiresAt?.let { "until $it" } ?: "forever"}"
8485
rejectLoginRequest(
8586
challenge,
86-
GenericError(
87+
RejectOAuth2Request(
8788
error = HYDRA_ERROR_USER_BANNED,
8889
errorDescription = errorDescription,
8990
statusCode = 403,
@@ -95,7 +96,7 @@ class HydraService(
9596
is LoginResult.TechnicalError -> {
9697
rejectLoginRequest(
9798
challenge,
98-
GenericError(
99+
RejectOAuth2Request(
99100
error = HYDRA_ERROR_TECHNICAL_ERROR,
100101
errorDescription = "Something went wrong while logging in. Please try again",
101102
statusCode = 500,
@@ -107,17 +108,17 @@ class HydraService(
107108
is LoginResult.SuccessfulLogin -> {
108109
val redirectResponse = hydraClient.acceptLoginRequest(
109110
challenge,
110-
AcceptLoginRequest(subject = loginResult.userId.toString()),
111+
AcceptOAuth2LoginRequest(subject = loginResult.userId.toString()),
111112
)
112113
LoginResponse.SuccessfulLogin(RedirectTo(redirectResponse.redirectTo))
113114
}
114115
}
115116
}
116117

117-
fun rejectLoginRequest(challenge: String, error: GenericError) {
118+
fun rejectLoginRequest(challenge: String, request: RejectOAuth2Request) {
118119
val redirectResponse = hydraClient.rejectLoginRequest(
119120
challenge,
120-
GenericError(
121+
RejectOAuth2Request(
121122
error = HYDRA_ERROR_TECHNICAL_ERROR,
122123
errorDescription = "Something went wrong while logging in. Please try again",
123124
statusCode = 500,
@@ -129,7 +130,7 @@ class HydraService(
129130
)
130131
}
131132

132-
fun getConsentRequest(challenge: String): ConsentRequest = hydraClient.getConsentRequest(challenge)
133+
fun getConsentRequest(challenge: String): OAuth2ConsentRequest = hydraClient.getConsentRequest(challenge)
133134

134135
@Transactional
135136
fun acceptConsentRequest(challenge: String): RedirectTo {
@@ -155,8 +156,8 @@ class HydraService(
155156

156157
val redirectResponse = hydraClient.acceptConsentRequest(
157158
challenge,
158-
AcceptConsentRequest(
159-
session = ConsentRequestSession(
159+
AcceptOAuth2ConsentRequest(
160+
session = AcceptOAuth2ConsentRequestSession(
160161
accessToken = context,
161162
idToken = context,
162163
),

src/main/kotlin/com/faforever/userservice/ui/view/oauth2/ConsentView.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout
1414
import com.vaadin.flow.router.BeforeEnterEvent
1515
import com.vaadin.flow.router.BeforeEnterObserver
1616
import com.vaadin.flow.router.Route
17-
import sh.ory.hydra.model.ConsentRequest
17+
import sh.ory.hydra.model.OAuth2ConsentRequest
1818

1919
@Route("/oauth2/consent", layout = CardLayout::class)
2020
class ConsentView(
@@ -51,7 +51,7 @@ class ConsentView(
5151
add(socialIcons)
5252
}
5353

54-
private fun setDetailsFromRequest(consentRequest: ConsentRequest) {
54+
private fun setDetailsFromRequest(consentRequest: OAuth2ConsentRequest) {
5555
consentRequest.client?.let { oAuthClientHeader.setClient(it) }
5656

5757
if (consentRequest.requestedScope.isNullOrEmpty()) {
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
/**
2-
* ORY Hydra
3-
* Welcome to the ORY Hydra HTTP API documentation. You will find documentation for all HTTP APIs here.
4-
*
5-
* The version of the OpenAPI document: latest
6-
*
7-
*
8-
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
9-
* https://openapi-generator.tech
10-
* Do not edit the class manually.
11-
*/
2+
*
3+
* Please note:
4+
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
5+
* Do not edit this file manually.
6+
*
7+
*/
8+
9+
@file:Suppress(
10+
"ArrayInDataClass",
11+
"EnumEntryName",
12+
"RemoveRedundantQualifierName",
13+
"UnusedImport",
14+
)
15+
1216
package sh.ory.hydra.model
1317

1418
import com.fasterxml.jackson.annotation.JsonProperty
15-
import io.quarkus.runtime.annotations.RegisterForReflection
1619

1720
/**
1821
*
22+
*
23+
* @param context
1924
* @param grantAccessTokenAudience
2025
* @param grantScope
2126
* @param handledAt
@@ -24,20 +29,29 @@ import io.quarkus.runtime.annotations.RegisterForReflection
2429
* @param session
2530
*/
2631

27-
@RegisterForReflection
28-
data class AcceptConsentRequest(
32+
data class AcceptOAuth2ConsentRequest(
33+
34+
@JsonProperty("context")
35+
val context: kotlin.Any? = null,
36+
2937
@JsonProperty("grant_access_token_audience")
3038
val grantAccessTokenAudience: kotlin.collections.List<kotlin.String>? = null,
39+
3140
@JsonProperty("grant_scope")
3241
val grantScope: kotlin.collections.List<kotlin.String>? = null,
42+
3343
@JsonProperty("handled_at")
3444
val handledAt: java.time.OffsetDateTime? = null,
45+
3546
/* Remember, if set to true, tells ORY Hydra to remember this consent authorization and reuse it if the same client asks the same user for the same, or a subset of, scope. */
3647
@JsonProperty("remember")
3748
val remember: kotlin.Boolean? = null,
49+
3850
/* RememberFor sets how long the consent authorization should be remembered for in seconds. If set to `0`, the authorization will be remembered indefinitely. */
3951
@JsonProperty("remember_for")
4052
val rememberFor: kotlin.Long? = null,
53+
4154
@JsonProperty("session")
42-
val session: ConsentRequestSession? = null,
55+
val session: AcceptOAuth2ConsentRequestSession? = null,
56+
4357
)
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,37 @@
11
/**
2-
* ORY Hydra
3-
* Welcome to the ORY Hydra HTTP API documentation. You will find documentation for all HTTP APIs here.
4-
*
5-
* The version of the OpenAPI document: latest
6-
*
7-
*
8-
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
9-
* https://openapi-generator.tech
10-
* Do not edit the class manually.
11-
*/
2+
*
3+
* Please note:
4+
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
5+
* Do not edit this file manually.
6+
*
7+
*/
8+
9+
@file:Suppress(
10+
"ArrayInDataClass",
11+
"EnumEntryName",
12+
"RemoveRedundantQualifierName",
13+
"UnusedImport",
14+
)
15+
1216
package sh.ory.hydra.model
1317

1418
import com.fasterxml.jackson.annotation.JsonProperty
15-
import io.quarkus.runtime.annotations.RegisterForReflection
1619

1720
/**
21+
*
1822
*
1923
* @param accessToken AccessToken sets session data for the access and refresh token, as well as any future tokens issued by the refresh grant. Keep in mind that this data will be available to anyone performing OAuth 2.0 Challenge Introspection. If only your services can perform OAuth 2.0 Challenge Introspection, this is usually fine. But if third parties can access that endpoint as well, sensitive data from the session might be exposed to them. Use with care!
2024
* @param idToken IDToken sets session data for the OpenID Connect ID token. Keep in mind that the session'id payloads are readable by anyone that has access to the ID Challenge. Use with care!
2125
*/
2226

23-
@RegisterForReflection
24-
data class ConsentRequestSession(
27+
data class AcceptOAuth2ConsentRequestSession(
28+
2529
/* AccessToken sets session data for the access and refresh token, as well as any future tokens issued by the refresh grant. Keep in mind that this data will be available to anyone performing OAuth 2.0 Challenge Introspection. If only your services can perform OAuth 2.0 Challenge Introspection, this is usually fine. But if third parties can access that endpoint as well, sensitive data from the session might be exposed to them. Use with care! */
2630
@JsonProperty("access_token")
2731
val accessToken: kotlin.Any? = null,
32+
2833
/* IDToken sets session data for the OpenID Connect ID token. Keep in mind that the session'id payloads are readable by anyone that has access to the ID Challenge. Use with care! */
2934
@JsonProperty("id_token")
3035
val idToken: kotlin.Any? = null,
36+
3137
)

0 commit comments

Comments
 (0)