> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Java Spring Boot

> Okta Spring Boot Starter を使用して、Spring Boot の Web アプリケーションに Auth0 のログインを追加します。

export const HowToSchema = () => <script type="application/ld+json">
    {'{"@context":"https://schema.org","@type":"HowTo"}'}
  </script>;

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

<HowToSchema />

<Note>
  **前提条件:**

  * JDK 17+ ([ダウンロード](https://adoptium.net/))
  * Maven 3.6+ または Gradle 7+ ([Maven](https://maven.apache.org/download.cgi) | [Gradle](https://gradle.org/install/))
  * IDE (IntelliJ IDEA、Eclipse、または VS Code を推奨)

  **Java バージョンの互換性:** Spring Boot 3.x+ および Okta Spring Boot Starter 3.x では、Java 17 以上が必要です。
</Note>

<div id="get-started">
  ## はじめに
</div>

このクイックスタートでは、Spring Boot の Web アプリケーションに Auth0 のログインを追加する方法を紹介します。Okta Spring Boot Starter を使って、ログイン、ログアウト、保護されたプロファイルページを備えた安全な Web アプリを構築します。これにより、Spring Security の OAuth2 ログインサポートが自動的に構成されます。

<Steps>
  <Step title="新しいプロジェクトを作成" stepNumber={1}>
    必要な依存関係を含む Spring Boot プロジェクトを作成します。

    <Tabs>
      <Tab title="Spring Initializr を使用する">
        ```bash theme={null}
        curl -L https://start.spring.io/starter.zip \
            -d dependencies=web,security,thymeleaf \
            -d javaVersion=17 \
            -d name=auth0-webapp \
            -d artifactId=auth0-webapp \
            -d packageName=com.auth0.example \
            -o auth0-webapp.zip

        mkdir auth0-webapp && unzip auth0-webapp.zip -d auth0-webapp && cd auth0-webapp
        ```
      </Tab>

      <Tab title="または Maven で手動で作成する">
        ```bash theme={null}
        mvn archetype:generate \
            -DgroupId=com.auth0 \
            -DartifactId=auth0-webapp \
            -DarchetypeArtifactId=maven-archetype-quickstart \
            -DinteractiveMode=false

        cd auth0-webapp
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Okta Spring Boot Starterを追加する" stepNumber={2}>
    Okta Spring Boot Starter の依存関係をプロジェクトに追加します。これにより、Auth0/Okta 向けの自動構成を含む Spring Security OAuth2 のログインサポートが追加されます。

    <Tabs>
      <Tab title="Maven (pom.xml)">
        ```xml theme={null}
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity6</artifactId>
        </dependency>
        <dependency>
            <groupId>com.okta.spring</groupId>
            <artifactId>okta-spring-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        ```
      </Tab>

      <Tab title="Gradle (build.gradle)">
        ```gradle theme={null}
        dependencies {
            implementation 'org.springframework.boot:spring-boot-starter-security'
            implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
            implementation 'org.springframework.boot:spring-boot-starter-web'
            implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
            implementation 'com.okta.spring:okta-spring-boot-starter:3.1.0'
            testImplementation 'org.springframework.boot:spring-boot-starter-test'
            testImplementation 'org.springframework.security:spring-security-test'
            testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
        }
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Auth0を設定する" stepNumber={3}>
    Auth0 テナントに Regular Web Application を作成し、プロジェクトに設定を追加します。

    CLIコマンドを実行して Auth0 アプリを自動的に設定する方法と、Auth0 Dashboardから手動で行う方法のいずれかを選択できます：

    <Tabs>
      <Tab title="CLI">
        Auth0 アプリケーションを作成して `src/main/resources/application.yml` を更新するには、プロジェクトのルートディレクトリで次のシェルコマンドを実行します。

        <CodeGroup>
          ```shellscript Mac theme={null}
          # Auth0 CLI をインストールします（まだインストールしていない場合）
          brew tap auth0/auth0-cli && brew install auth0

          # Auth0 アプリを設定し、application.yml を生成します
          auth0 qs setup --app --type regular --framework spring-boot --build-tool maven --port 3000 --name "My Spring Boot App"
          ```

          ```powershell Windows theme={null}
          # Auth0 CLI をインストールします（まだインストールしていない場合）
          scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
          scoop install auth0

          # Auth0 アプリを設定し、application.yml を生成します
          auth0 qs setup --app --type regular --framework spring-boot --build-tool maven --port 3000 --name "My Spring Boot App"
          ```
        </CodeGroup>

        <Note>
          このコマンドは次を実行します：

          1. 認証済みかどうかを確認します (必要に応じてログインを促します)
          2. `http://localhost:3000` 用に設定された Auth0 Regular Web Application を作成します
          3. `okta.oauth2.issuer`、`okta.oauth2.client-id`、`okta.oauth2.client-secret` を含む `src/main/resources/application.yml` を生成します

          Gradle を使用する場合は、`--build-tool maven` を `--build-tool gradle` に置き換えてください。
        </Note>
      </Tab>

      <Tab title="Auth0 Dashboard">
        始める前に、`src/main/resources/application.yml` ファイルに Auth0 の設定を追加してください:

        ```yaml src/main/resources/application.yml expandable theme={null}
        server:
          port: 3000

        okta:
          oauth2:
            issuer: "https://YOUR_AUTH0_DOMAIN/"
            client-id: "YOUR_CLIENT_ID"
            client-secret: "YOUR_CLIENT_SECRET"
        ```

        1. [Auth0 Dashboard](https://manage.auth0.com) → **アプリケーション** → **アプリケーション** に移動します。
        2. **Create Application** を選択します。
        3. 名前 (例: "My Spring Boot Webapp") を入力し、**従来型Webアプリケーション** を選択します。
        4. **Create** を選択します。
        5. **Application Settings** タブに移動し、以下を設定します。
           * **Allowed Callback URLs**: `http://localhost:3000/login/oauth2/code/okta`
           * **Allowed Logout URLs**: `http://localhost:3000/`
        6. **Application Settings** タブで **Domain**、**Client ID**、**Client Secret** をコピーします。
        7. `application.yml` 内のプレースホルダー値を置き換えます。

        <Info>
          **Callback URL** は完全に一致している必要があります。Spring Security の OAuth2 ログインでは、デフォルトで `/login/oauth2/code/okta` パスが使用されます。

          **Issuer** には `https://` と末尾の `/` を含める必要があります。使用するのはドメインとリージョンのみです。例: `https://dev-abc123.us.auth0.com/`。
        </Info>
      </Tab>
    </Tabs>
  </Step>

  <Step title="認証を設定する" stepNumber={4}>
    OAuth2によるログインを有効にし、Auth0のログアウトを処理するセキュリティ設定を作成します。未認証のユーザーは自動的にAuth0のログインページへリダイレクトされます。

    ```java lines expandable theme={null}
    // src/main/java/com/auth0/example/SecurityConfig.java

    package com.auth0.example;

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.web.SecurityFilterChain;
    import org.springframework.security.web.authentication.logout.LogoutHandler;
    import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

    import java.io.IOException;

    import static org.springframework.security.config.Customizer.withDefaults;

    @Configuration
    public class SecurityConfig {

        @Value("${okta.oauth2.issuer}")
        private String issuer;
        @Value("${okta.oauth2.client-id}")
        private String clientId;

        @Bean
        public SecurityFilterChain configure(HttpSecurity http) throws Exception {
            http
                .authorizeHttpRequests(authorize -> authorize
                    .requestMatchers("/", "/images/**").permitAll()
                    .anyRequest().authenticated()
                )
                .oauth2Login(withDefaults())
                .logout(logout -> logout
                    .addLogoutHandler(logoutHandler()));
            return http.build();
        }

        private LogoutHandler logoutHandler() {
            return (request, response, authentication) -> {
                try {
                    String baseUrl = ServletUriComponentsBuilder.fromCurrentContextPath().build().toUriString();
                    response.sendRedirect(issuer + "v2/logout?client_id=" + clientId + "&returnTo=" + baseUrl);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            };
        }
    }
    ```
  </Step>

  <Step title="コントローラーとビューを作成する" stepNumber={5}>
    ホームページとプロファイルページ用のコントローラーと Thymeleaf テンプレートを作成します。

    <AuthCodeGroup>
      ```java src/main/java/com/auth0/example/HomeController.java expandable lines theme={null}
      package com.auth0.example;

      import org.springframework.security.core.annotation.AuthenticationPrincipal;
      import org.springframework.security.oauth2.core.oidc.user.OidcUser;
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.Model;
      import org.springframework.web.bind.annotation.GetMapping;

      @Controller
      public class HomeController {

          @GetMapping("/")
          public String home(Model model, @AuthenticationPrincipal OidcUser principal) {
              if (principal != null) {
                  model.addAttribute("profile", principal.getClaims());
              }
              return "index";
          }
      }
      ```

      ```java src/main/java/com/auth0/example/ProfileController.java expandable lines theme={null}
      package com.auth0.example;

      import com.fasterxml.jackson.core.JsonProcessingException;
      import com.fasterxml.jackson.databind.ObjectMapper;
      import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
      import org.springframework.security.core.annotation.AuthenticationPrincipal;
      import org.springframework.security.oauth2.core.oidc.user.OidcUser;
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.Model;
      import org.springframework.web.bind.annotation.GetMapping;

      import java.util.Map;

      @Controller
      public class ProfileController {

          private final static ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());

          @GetMapping("/profile")
          public String profile(Model model, @AuthenticationPrincipal OidcUser oidcUser) {
              model.addAttribute("profile", oidcUser.getClaims());
              model.addAttribute("profileJson", claimsToJson(oidcUser.getClaims()));
              return "profile";
          }

          private String claimsToJson(Map<String, Object> claims) {
              try {
                  return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(claims);
              } catch (JsonProcessingException jpe) {
                  return "Error parsing claims to JSON.";
              }
          }
      }
      ```

      ```html src/main/resources/templates/index.html expandable lines theme={null}
      <!DOCTYPE html>
      <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
      <head>
          <meta charset="UTF-8">
          <title>Auth0 Spring Boot Login</title>
      </head>
      <body>
          <h1>Auth0 Spring Boot Login Sample</h1>

          <div sec:authorize="!isAuthenticated()">
              <p>You are not logged in.</p>
              <a href="/oauth2/authorization/okta">Login</a>
          </div>

          <div sec:authorize="isAuthenticated()">
              <p>Welcome, <span sec:authentication="name">User</span>!</p>
              <ul>
                  <li><a href="/profile">View Profile</a></li>
                  <li>
                      <form th:action="@{/logout}" method="post" style="display:inline;">
                          <button type="submit">Logout</button>
                      </form>
                  </li>
              </ul>
          </div>
      </body>
      </html>
      ```

      ```html src/main/resources/templates/profile.html expandable lines theme={null}
      <!DOCTYPE html>
      <html lang="en" xmlns:th="http://www.thymeleaf.org">
      <head>
          <meta charset="UTF-8">
          <title>User Profile</title>
      </head>
      <body>
          <h1>User Profile</h1>
          <a href="/">Home</a>

          <div th:if="${profile}">
              <img th:if="${profile['picture']}" th:src="${profile['picture']}" width="64" height="64" alt="Profile picture" />
              <h2 th:text="${profile['name']}">Name</h2>
              <p th:text="${profile['email']}">Email</p>
          </div>

          <h3>All Claims</h3>
          <pre th:text="${profileJson}">Claims JSON</pre>

          <form th:action="@{/logout}" method="post">
              <button type="submit">Logout</button>
          </form>
      </body>
      </html>
      ```
    </AuthCodeGroup>
  </Step>

  <Step title="アプリケーションを実行" stepNumber={6}>
    Maven または Gradle のラッパーを使ってアプリケーションを起動します。

    <Tabs>
      <Tab title="Maven">
        ```bash theme={null}
        ./mvnw spring-boot:run
        ```
      </Tab>

      <Tab title="Gradle">
        ```bash theme={null}
        ./gradlew bootRun
        ```
      </Tab>
    </Tabs>

    アプリケーションは `http://localhost:3000` で起動します。Auth0 のログインフローをトリガーするには、`http://localhost:3000/profile` にアクセスします。
  </Step>
</Steps>

<Check>
  これで、Auth0ログインを備えた完全に機能する Spring Boot の Web アプリケーションが [localhost](http://localhost:3000/) で動作しているはずです。ホームページは公開されており、`/profile` にアクセスすると、未認証のユーザーは Auth0 のログインページにリダイレクトされます。
</Check>

***

<div id="advanced-usage">
  ## 高度な使い方
</div>

<Accordion title="ユーザープロファイルのクレームにアクセスする">
  `@AuthenticationPrincipal OidcUser` パラメーターを使用すると、ID トークン内のすべてのクレームにアクセスできます。`getClaims()` を使ってクレーム一式を取得することも、特定のクレーム用の getter メソッドを個別に使うこともできます。

  ```java theme={null}
  @GetMapping("/profile")
  public String profile(Model model, @AuthenticationPrincipal OidcUser oidcUser) {
      model.addAttribute("name", oidcUser.getFullName());
      model.addAttribute("email", oidcUser.getEmail());
      model.addAttribute("picture", oidcUser.getPicture());
      model.addAttribute("sub", oidcUser.getSubject());
      model.addAttribute("allClaims", oidcUser.getClaims());
      return "profile";
  }
  ```
</Accordion>

<Accordion title="ロールベースのアクセス制御">
  Auth0 のロールに基づいて、ページへのアクセスを制限できます。まず Auth0 Action を使ってロールを ID トークンに追加し、次にセキュリティ設定で `hasAuthority()` を使用します。

  ### トークンにロールを追加する

  1. [Auth0 Dashboard](https://manage.auth0.com) → **Actions** → **Flows** → **Login** に移動します。
  2. ロールをカスタムクレームとして ID トークンに追加するカスタム Action を作成します。

  ```javascript theme={null}
  exports.onExecutePostLogin = async (event, api) => {
    const namespace = "https://my-app.example.com";
    if (event.authorization) {
      api.idToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
    }
  };
  ```

  ### 認可を設定する

  特定のロールを endpoint で必須にするよう、`SecurityConfig` を更新します。

  ```java expandable theme={null}
  @Bean
  public SecurityFilterChain configure(HttpSecurity http) throws Exception {
      http
          .authorizeHttpRequests(authorize -> authorize
              .requestMatchers("/", "/images/**").permitAll()
              .requestMatchers("/admin/**").hasAuthority("ROLE_admin")
              .anyRequest().authenticated()
          )
          .oauth2Login(withDefaults())
          .logout(logout -> logout
              .addLogoutHandler(logoutHandler()));
      return http.build();
  }
  ```
</Accordion>

<Accordion title="権限のカスタムマッピング">
  Okta starter は、`AuthoritiesProvider` インターフェースを通じて権限のカスタムマッピングをサポートしています。ユーザー属性や外部データソースに基づいてカスタム `GrantedAuthority` オブジェクトを追加するには、bean を登録します。

  ```java expandable theme={null}
  package com.auth0.example;

  import com.okta.spring.boot.oauth.AuthoritiesProvider;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.security.core.GrantedAuthority;
  import org.springframework.security.core.authority.SimpleGrantedAuthority;

  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;

  @Configuration
  public class AuthoritiesConfig {

      @Bean
      AuthoritiesProvider customAuthoritiesProvider() {
          return (user, userRequest) -> {
              Set<GrantedAuthority> authorities = new HashSet<>();

              // カスタム roles クレームを Spring Security の権限にマッピングする
              Object roles = user.getAttribute("https://my-app.example.com/roles");
              if (roles instanceof List<?> roleList) {
                  roleList.forEach(role ->
                      authorities.add(new SimpleGrantedAuthority("ROLE_" + role))
                  );
              }

              return authorities;
          };
      }
  }
  ```
</Accordion>

***

<div id="common-issues">
  ## よくある問題
</div>

<AccordionGroup>
  <Accordion title="ログインへのリダイレクトに失敗する - 無効なコールバック URL">
    ログインを選択すると、コールバック URL の不一致に関するエラーが Auth0 に表示されます。

    Auth0 アプリケーションの **Allowed Callback URLs** は、Spring Security が使用するコールバック URL と完全に一致している必要があります。デフォルトは `http://localhost:3000/login/oauth2/code/okta` です。

    1. [Auth0 Dashboard](https://manage.auth0.com) で、**アプリケーション** → Your App → **Settings** に移動します。
    2. **Allowed Callback URLs** に `http://localhost:3000/login/oauth2/code/okta` を追加します。
    3. **Save Changes** を選択します。
  </Accordion>

  <Accordion title="起動時に issuer が無効になる">
    issuer の不一致により、アプリケーションの起動またはログインに失敗します。

    `okta.oauth2.issuer` には、`https://` と末尾の `/` を含む完全な Auth0 テナント URL を指定する必要があります。

    ```yaml theme={null}
    # ❌ 誤り - https:// または末尾のスラッシュがない
    okta:
      oauth2:
        issuer: "dev-abc123.us.auth0.com"

    # ✅ 正しい - 末尾のスラッシュを含む完全な URL
    okta:
      oauth2:
        issuer: "https://dev-abc123.us.auth0.com/"
    ```
  </Accordion>

  <Accordion title="起動時に OIDC ディスカバリーが失敗する">
    `/.well-known/openid-configuration` の取得時に接続エラーが発生し、アプリケーションの起動に失敗します。

    Okta Spring Boot Starter は、起動時に issuer URL から OpenID Connect のディスカバリードキュメントを取得します。issuer URL が正しく、ネットワークから到達可能であることを確認してください。社内の firewall 配下にある場合は、プロキシを設定してください。

    ```yaml theme={null}
    okta:
      oauth2:
        issuer: "https://dev-abc123.us.auth0.com/"
        proxy:
          host: "proxy.example.com"
          port: 8080
    ```
  </Accordion>

  <Accordion title="設定値が見つからない">
    アプリケーションは起動しますが、設定プロパティが読み込まれていないためログインに失敗します。

    `application.yml` で、`okta.oauth2` 名前空間の下に正しい YAML のインデントが使われていることを確認してください。

    ```yaml theme={null}
    # ❌ 誤り - フラットな構造で、ネストされていない
    okta.oauth2.issuer: "https://dev-abc123.us.auth0.com/"

    # ✅ 正しい - 適切にネストされた YAML
    okta:
      oauth2:
        issuer: "https://dev-abc123.us.auth0.com/"
        client-id: "YOUR_CLIENT_ID"
        client-secret: "YOUR_CLIENT_SECRET"
    ```
  </Accordion>

  <Accordion title="Logout で Auth0 セッションがクリアされない">
    ログアウトを選択すると、Auth0 のログインページが表示されないまま、ユーザーがすぐに再度ログインされます。

    `SecurityConfig` に、Auth0 の `/v2/logout` エンドポイントにリダイレクトするカスタム `LogoutHandler` が含まれていることを確認してください。あわせて、Auth0 の **Application Settings** の **Allowed Logout URLs** に `http://localhost:3000/` が含まれていることも確認してください。
  </Accordion>
</AccordionGroup>

***

<div id="additional-resources">
  ## 追加リソース
</div>

<CardGroup cols={3}>
  <Card title="SDKドキュメント" icon="book" href="https://github.com/okta/okta-spring-boot">
    SDK の完全なドキュメント、ソースコード、リリースノート
  </Card>

  <Card title="Auth0ドキュメント" icon="file-lines" href="https://auth0.com/docs">
    Spring Boot アプリケーション向けの Auth0 公式ドキュメント
  </Card>

  <Card title="Spring Securityリファレンス" icon="shield" href="https://docs.spring.io/spring-security/reference/servlet/oauth2/login.html">
    Spring Security OAuth2 Login のドキュメント
  </Card>

  <Card title="設定リファレンス" icon="gear" href="https://github.com/okta/okta-spring-boot#configuration-reference">
    使用可能なすべての okta.oauth2.\* 設定プロパティ
  </Card>

  <Card title="Auth0 Dashboard" icon="browser" href="https://manage.auth0.com/">
    Auth0 の API とアプリケーションを管理
  </Card>

  <Card title="コミュニティフォーラム" icon="comments" href="https://community.auth0.com/">
    Auth0 コミュニティからサポートを受ける
  </Card>
</CardGroup>

***

<div id="sample-application">
  ## サンプルアプリケーション
</div>

Auth0 を使ったログイン、プロファイル表示、ログアウトを実装した完全なサンプルアプリケーションは、Auth0 のサンプルリポジトリで公開されています。

<Card title="MVC Login サンプル" icon="github" href="https://github.com/auth0-samples/auth0-spring-boot-login-samples/tree/master/mvc-login">
  Auth0 OAuth2 連携によるログイン、ログアウト、プロファイルページが含まれています
</Card>

クローンして実行:

```bash theme={null}
git clone https://github.com/auth0-samples/auth0-spring-boot-login-samples.git
cd auth0-spring-boot-login-samples/mvc-login

# Auth0の設定でsrc/main/resources/application.ymlを更新してください
# 次に実行してください:
./gradlew bootRun
```

ブラウザで `http://localhost:3000` を開き、**Login** リンクを選択して Auth0 のログインフローをテストします。
