Repository: sebadob/rauthy (language: rust)

Issue:
REST API normalize case convention
Presently if looking over the endpoints from the Swagger docs, there is some inconsistency here. Might be worthwhile to normalize to `kebab-case` which is generally most appropriate for URLs?

Some endpoints are using `snake_case` and `camelCase`, and from the looks of it some like `sessioninfo` perhaps should be `session-info`?


Discussion / hints:
Yes, that is on the TODO for the next smaller release.

I will deprecate any inconsistent endpoints and keep them around for 1 release to make any migrations easy.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed0ee6ebb..4a09760d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
 # Changelog
 
-## NIGHTLY 0.25.0-20240805
+## UNRELEASED
 
 ### Changes
 
@@ -23,7 +23,30 @@ application. If so, you can disable the authentication on this endpoint with
 DANGER_DISABLE_INTROSPECT_AUTH=true
 ```
 
-[]()
+[2e84ceb](https://github.com/sebadob/rauthy/commit/2e84ceb062c677e863f5ad524c7fe8b2af21449b)
+[7087a59](https://github.com/sebadob/rauthy/commit/7087a5998f5c687c6b7bd90a0771451ddec9068e)
+
+#### API Routes Normalization
+
+In preparation for a clean v1.0.0, some older API routes have been fixed regarding their casing and naming.
+The "current" or old routes and names will be available for exactly one release and will be phased out afterward
+to have a smooth migration, just in case someone uses these renamed routes.
+
+- `/oidc/tokenInfo` -> `/oidc/introspect`
+- `/oidc/rotateJwk` -> `/oidc/rotate_jwk`
+
+Since I don't like `kebab-case`, most API routes are written in `snake_case`, with 2 exceptions that follow RFC namings:
+
+- `openid-configuration`
+- `web-identity`
+
+All the `*info` routes like `userinfo` or `sessioninfo` are not `kebab_case` on purpose, just to match other IdPs and
+RFCs a bit more.
+
+There is not a single `camelCase` anymore in the API routes to avoid confusion and issues in situations where you could
+mistake an uppercase `I` as a lowercase `l`. The current `camelCase` endpoints only exist for a smoother migration and
+will be phased out with the next bigger release.
+
 []()
 
 #### Config Read
diff --git a/Cargo.lock b/Cargo.lock
index 67aa78321..b9f9c7bab 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -79,7 +79,7 @@ dependencies = [
  "brotli",
  "bytes",
  "bytestring",
- "derive_more",
+ "derive_more 0.99.18",
  "encoding_rs",
  "flate2",
  "futures-core",
@@ -121,7 +121,7 @@ dependencies = [
  "actix-multipart-derive",
  "actix-utils",
  "actix-web",
- "derive_more",
+ "derive_more 0.99.18",
  "futures-core",
  "futures-util",
  "httparse",
@@ -253,7 +253,7 @@ dependencies = [
  "bytestring",
  "cfg-if",
  "cookie",
- "derive_more",
+ "derive_more 0.99.18",
  "encoding_rs",
  "futures-core",
  "futures-util",
@@ -306,9 +306,9 @@ dependencies = [
 
 [[package]]
 name = "actix-web-lab"
-version = "0.20.2"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7675c1a84eec1b179c844cdea8488e3e409d8e4984026e92fa96c87dd86f33c6"
+checksum = "2a965e3e826aa4737af33666aa09ed949aa1837706fda2adee07039347be50d6"
 dependencies = [
  "actix-http",
  "actix-router",
@@ -318,16 +318,16 @@ dependencies = [
  "actix-web-lab-derive",
  "ahash",
  "arc-swap",
- "async-trait",
  "bytes",
  "bytestring",
  "csv",
- "derive_more",
+ "derive_more 1.0.0",
+ "form_urlencoded",
  "futures-core",
  "futures-util",
  "http 0.2.12",
  "impl-more",
- "itertools 0.12.1",
+ "itertools 0.13.0",
  "local-channel",
  "mediatype",
  "mime",
@@ -337,6 +337,7 @@ dependencies = [
  "serde",
  "serde_html_form",
  "serde_json",
+ "serde_path_to_error",
  "tokio",
  "tokio-stream",
  "tracing",
@@ -344,9 +345,9 @@ dependencies = [
 
 [[package]]
 name = "actix-web-lab-derive"
-version = "0.20.0"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aa0b287c8de4a76b691f29dbb5451e8dd5b79d777eaf87350c9b0cbfdb5e968"
+checksum = "008f98f5a68eeacf5e6d44ed74ce03c1b906baa53eabfb41faf0f5f40bd685f8"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1685,6 +1686,27 @@ dependencies = [
  "syn 2.0.72",
 ]
 
+[[package]]
+name = "derive_more"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
+dependencies = [
+ "derive_more-impl",
+]
+
+[[package]]
+name = "derive_more-impl"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.72",
+ "unicode-xid",
+]
+
 [[package]]
 name = "diff"
 version = "0.1.13"
@@ -4179,7 +4201,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "actix-service",
  "actix-web",
@@ -4220,7 +4242,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy-api-types"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "actix-web",
  "chrono",
@@ -4242,7 +4264,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy-common"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "actix-web",
  "argon2",
@@ -4268,7 +4290,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy-error"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "actix-multipart",
  "actix-web",
@@ -4279,7 +4301,7 @@ dependencies = [
  "chrono",
  "cryptr",
  "css-color",
- "derive_more",
+ "derive_more 1.0.0",
  "flume",
  "image",
  "oxiri",
@@ -4302,7 +4324,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy-handlers"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "actix-multipart",
  "actix-web",
@@ -4333,7 +4355,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy-middlewares"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "actix-web",
  "chrono",
@@ -4352,7 +4374,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy-models"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "accept-language",
  "actix",
@@ -4371,7 +4393,7 @@ dependencies = [
  "chrono",
  "cryptr",
  "css-color",
- "derive_more",
+ "derive_more 1.0.0",
  "dotenvy",
  "ed25519-compact",
  "flume",
@@ -4424,7 +4446,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy-notify"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "async-trait",
  "chrono",
@@ -4443,7 +4465,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy-schedulers"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "actix-web",
  "chrono",
@@ -4461,7 +4483,7 @@ dependencies = [
 
 [[package]]
 name = "rauthy-service"
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 dependencies = [
  "actix-web",
  "argon2",
@@ -4470,7 +4492,7 @@ dependencies = [
  "chacha20poly1305",
  "chrono",
  "cryptr",
- "derive_more",
+ "derive_more 1.0.0",
  "jwt-simple",
  "pretty_assertions",
  "rand",
@@ -5356,6 +5378,16 @@ dependencies = [
  "syn 2.0.72",
 ]
 
+[[package]]
+name = "serde_path_to_error"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
+dependencies = [
+ "itoa",
+ "serde",
+]
+
 [[package]]
 name = "serde_plain"
 version = "1.0.2"
diff --git a/Cargo.toml b/Cargo.toml
index 33a9ac2db..04f3e50d9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,7 @@ members = ["src/*"]
 exclude = ["rauthy-client"]
 
 [workspace.package]
-version = "0.25.0-20240809"
+version = "0.25.0-20240824"
 edition = "2021"
 authors = ["Sebastian Dobe <sebastiandobe@mailbox.org>"]
 license = "Apache-2.0"
@@ -25,7 +25,7 @@ actix-multipart = "0.7.2"
 actix-service = "2"
 actix-web = { version = "4", features = ["rustls-0_23"] }
 actix-web-actors = "4"
-actix-web-lab = "0.20"
+actix-web-lab = "0.22"
 actix-web-prom = "0.8.0"
 actix-web-validator = "6"
 anyhow = "1"
@@ -42,7 +42,7 @@ cidr = "0.2.2"
 cron = "0.12"
 cryptr = { version = "0.5.1", features = ["s3", "streaming"] }
 css-color = "0.2"
-derive_more = "0.99"
+derive_more = "1"
 dotenvy = "0.15"
 ed25519-compact = { version = "2.0.4", features = ["ed25519"] }
 flume = "0.11"
diff --git a/frontend/src/utils/dataFetchingAdmin.js b/frontend/src/utils/dataFetchingAdmin.js
index a83935b8c..66325c8d1 100644
--- a/frontend/src/utils/dataFetchingAdmin.js
+++ b/frontend/src/utils/dataFetchingAdmin.js
@@ -292,7 +292,7 @@ export async function postProviderLookup(data) {
 }
 
 export async function postRotateJwk() {
-    const res = await fetch(`/auth/v1/oidc/rotateJwk`, {
+    const res = await fetch(`/auth/v1/oidc/rotate_jwk`, {
         method: 'POST',
         headers: getHeaders(),
     });
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index b3e3eb159..600ab1e78 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -31,7 +31,7 @@ const config = {
             '/auth/v1/oidc/certs': backend,
             '/auth/v1/oidc/device': backend,
             '/auth/v1/oidc/logout': backend,
-            '/auth/v1/oidc/rotateJwk': backend,
+            '/auth/v1/oidc/rotate_jwk': backend,
             '/auth/v1/oidc/sessioninfo': backend,
             '/auth/v1/oidc/token': backend,
             '/auth/v1/clients': backend,
diff --git a/src/api/src/oidc.rs b/src/api/src/oidc.rs
index f6c733b8a..280224e47 100644
--- a/src/api/src/oidc.rs
+++ b/src/api/src/oidc.rs
@@ -699,14 +699,14 @@ pub async fn post_logout(
 /// - rauthy_admin
 #[utoipa::path(
     post,
-    path = "/oidc/rotateJwk",
+    path = "/oidc/rotate_jwk",
     tag = "oidc",
     responses(
         (status = 200, description = "Ok"),
         (status = 401, description = "Unauthorized", body = ErrorResponse),
     ),
 )]
-#[post("/oidc/rotateJwk")]
+#[post("/oidc/rotate_jwk")]
 pub async fn rotate_jwk(
     data: web::Data<AppState>,
     principal: ReqPrincipal,
@@ -718,6 +718,18 @@ pub async fn rotate_jwk(
         .map(|_| HttpResponse::Ok().finish())
 }
 
+#[post("/oidc/rotateJwk")]
+pub async fn rotate_jwk_deprecated(
+    data: web::Data<AppState>,
+    principal: ReqPrincipal,
+) -> Result<HttpResponse, ErrorResponse> {
+    principal.validate_api_key_or_admin_session(AccessGroup::Secrets, AccessRights::Update)?;
+
+    JWKS::rotate(&data)
+        .await
+        .map(|_| HttpResponse::Ok().finish())
+}
+
 /// Create a new session
 ///
 /// You can use this endpoint to create a new session outside the `/authorize` page when logging
diff --git a/src/bin/src/main.rs b/src/bin/src/main.rs
index e4a2faced..9edd595fb 100644
--- a/src/bin/src/main.rs
+++ b/src/bin/src/main.rs
@@ -545,6 +545,7 @@ async fn actix_main(app_state: web::Data<AppState>) -> std::io::Result<()> {
                             .service(oidc::get_logout)
                             .service(oidc::post_logout)
                             .service(oidc::rotate_jwk)
+                            .service(oidc::rotate_jwk_deprecated)
                             .service(oidc::post_session)
                             .service(oidc::get_session_info)
                             .service(oidc::get_session_xsrf)
diff --git a/src/error/src/lib.rs b/src/error/src/lib.rs
index b64115cf3..828273ac2 100644
--- a/src/error/src/lib.rs
+++ b/src/error/src/lib.rs
@@ -1,7 +1,7 @@
 use derive_more::Display;
 use serde::{Deserialize, Serialize};
 use std::borrow::Cow;
-use std::fmt::{Display, Formatter};
+use std::fmt::Formatter;
 use utoipa::ToSchema;
 
 pub mod error_impls;
@@ -45,7 +45,7 @@ impl Display for ErrorResponseType {
 // Except for input validations, every error will have this format and every possible error in the
 // backend will be converted to this.
 #[derive(Debug, Clone, Display, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
-#[display(fmt = "error: {} message: {}", error, message)]
+#[display("error: {} message: {}", error, message)]
 pub struct ErrorResponse {
     pub timestamp: i64,
     pub error: ErrorResponseType,


Test patch:
diff --git a/src/bin/tests/handler_auth.rs b/src/bin/tests/handler_auth.rs
index 0e38709ae..a8a69a07d 100644
--- a/src/bin/tests/handler_auth.rs
+++ b/src/bin/tests/handler_auth.rs
@@ -52,7 +52,7 @@ async fn test_certs() -> Result<(), Box<dyn Error>> {
     //     aw!(reqwest::get(&url)).unwrap();
     // }
     // rotate JWKs
-    let url_rotate = format!("{}/oidc/rotateJwk", backend_url);
+    let url_rotate = format!("{}/oidc/rotate_jwk", backend_url);
     let res = reqwest::Client::new()
         .post(&url_rotate)
         .headers(auth_headers.clone())