- Spring
Spring BootでGoogleログイン|OAuth2 Clientの完成コード
Spring Boot で Google ログインを付けるには、spring-boot-starter-security-oauth2-client を入れて、application.yml に Google の client-id と client-secret を書きます。 これだけで、ログインしていない人は自動で Google の画面に送られ、ログイン後にアプリへ戻ってきます。Google Cloud コンソールには、リダイレクト URI として http://localhost:8080/login/oauth2/code/google を登録します。
spring:
security:
oauth2:
client:
registration:
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}
| やること | 場所 | 値 |
|---|---|---|
| OAuth クライアント ID を作る | Google Cloud コンソール | 種類は「ウェブ アプリケーション」 |
| リダイレクト URI を登録 | 同上「承認済みのリダイレクト URI」 | http://localhost:8080/login/oauth2/code/google |
| 依存を足す | build.gradle.kts |
spring-boot-starter-security-oauth2-client |
| ID とシークレットを書く | application.yml |
上のとおり(環境変数から読む) |
| 画面を守る・ログアウト | SecurityFilterChain |
下の完成コード |
確認環境:Spring Boot 4.1.1・Spring Security 7.1.1(Spring Framework 7.0.9)。Google 用の既定値(スコープ・エンドポイント)、リダイレクト URI の形、エラーコードとメッセージ、Boot の自動設定は、Spring Security 7.1.1 と Spring Boot v4.1.1 のソース(GitHub のタグ)で確かめました。Google 側のエラーと ID トークンの項目は Google for Developers のドキュメントで確かめています(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Spring BootでGoogleログイン|OAuth2 Clientの完成コード」
しくみ:どこからどこへ移動するか
Google ログインは、OpenID Connect(OAuth 2.0 の上に「誰がログインしたか」を伝える部分を足した仕様)の「認可コードフロー」で動きます。
- ブラウザが
/を開く。ログインしていないので/oauth2/authorization/googleへ移る - Spring がランダムな
state(なりすまし防止の値)とnonceを作ってセッションに保存し、Google の認可画面(https://accounts.google.com/o/oauth2/v2/auth)へ移す - 利用者が Google でログインし、同意する
- Google が
/login/oauth2/code/google?code=…&state=…へ戻す(これがリダイレクト URI) - Spring が
stateを照合し、codeをトークンエンドポイントへ送って ID トークンとアクセストークンを受け取る - ID トークンの署名・発行者・宛先・
nonceを確かめ、ログイン済みにする
OAuth 2.0 と OpenID Connect の違いは、関連記事「OAuth 2.0とOpenID Connectの違いをわかりやすく解説」で扱っています。
Google 用の既定値(Spring Security 7.1.1 のソース)
registration の名前を google にすると、Spring Security の CommonOAuth2Provider.GOOGLE の値が自動で入ります。そのため client-id と client-secret だけで動きます。
| 項目 | 既定値 |
|---|---|
| スコープ | openid・profile・email |
| 認可エンドポイント | https://accounts.google.com/o/oauth2/v2/auth |
| トークンエンドポイント | https://www.googleapis.com/oauth2/v4/token |
| 公開鍵(JWK Set) | https://www.googleapis.com/oauth2/v3/certs |
| 発行者(issuer) | https://accounts.google.com |
| ユーザー情報 | https://www.googleapis.com/oauth2/v3/userinfo |
| ユーザー名に使う項目 | sub |
| クライアント認証 | client_secret_basic(Basic 認証ヘッダーで送る) |
| リダイレクト URI | {baseUrl}/{action}/oauth2/code/{registrationId} |
| 画面の表示名 | Google |
リダイレクト URI の {action} は、ログインでは login になります。{registrationId} は application.yml の registration の下に書いた名前です。名前を google-login などに変えると、リダイレクト URI も /login/oauth2/code/google-login に変わります。 そのときは provider: google を足します(足さないと下の「起動時のエラー」になります)。
Google Cloud コンソールの設定
- Google Cloud コンソールでプロジェクトを選ぶ
- 「Google Auth Platform」(旧「OAuth 同意画面」)で、アプリ名・サポートメール・対象(内部/外部)を設定する
- 「クライアント」で「クライアントを作成」→ 種類「ウェブ アプリケーション」
- 「承認済みのリダイレクト URI」に、環境ごとに URI を登録する
- 表示されたクライアント ID とクライアント シークレットを控える
| 環境 | 登録するリダイレクト URI |
|---|---|
| 手元 | http://localhost:8080/login/oauth2/code/google |
| 本番 | https://app.example.com/login/oauth2/code/google |
| コンテキストパスあり | https://example.com/myapp/login/oauth2/code/google |
Google のドキュメントでは、リダイレクト URI には次の決まりがあります。
- https であること(localhost と localhost の IP アドレスは例外)
- ホストに IP アドレスは使えない(localhost の IP アドレスは例外)
- トップレベルドメインが公開サフィックスリストにあること
localhost と 127.0.0.1 は別の URI として扱われます。 ブラウザで開いたほうと同じものを登録します。
完成コード
依存(build.gradle.kts)
plugins {
java
id("org.springframework.boot") version "4.1.1"
id("io.spring.dependency-management") version "1.1.7"
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-webmvc")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
implementation("org.springframework.boot:spring-boot-starter-security-oauth2-client")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
runtimeOnly("org.postgresql:postgresql")
}
Boot 4.1.1 のソースでは、Boot 3 までの spring-boot-starter-oauth2-client は「spring-boot-starter-security-oauth2-client に置き換えられた(deprecated)」と説明されています。中身の依存は同じです。starter の新旧の対応は、関連記事「Spring Boot starter一覧|用途別の選び方とBoot 4の新旧対応表」で扱っています。
application.yml
spring:
security:
oauth2:
client:
registration:
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}
# scope を書くと既定(openid, profile, email)を置き換える
# scope: openid, profile, email
server:
# リバースプロキシ(nginx・ロードバランサー)の後ろで https を正しく扱う
forward-headers-strategy: native
logging:
level:
# ログイン失敗の本当の理由を見るとき
org.springframework.security: DEBUG
client-secret はリポジトリに書かず、環境変数などから渡します。プロファイルごとの設定の分け方は、関連記事「Spring Bootプロファイル切り替え|application.ymlと優先順位」で扱っています。
SecurityFilterChain
package com.example.auth;
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.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http,
ClientRegistrationRepository repo,
AppOidcUserService oidcUserService) throws Exception {
// Google の画面に毎回アカウント選択を出す
var resolver = new DefaultOAuth2AuthorizationRequestResolver(
repo, OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
resolver.setAuthorizationRequestCustomizer(
c -> c.additionalParameters(p -> p.put("prompt", "select_account")));
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/login", "/error", "/css/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated())
.oauth2Login(o -> o
.loginPage("/login") // 自前のログイン画面
.authorizationEndpoint(a -> a.authorizationRequestResolver(resolver))
.userInfoEndpoint(u -> u.oidcUserService(oidcUserService)) // DB と紐づける
.defaultSuccessUrl("/home", true)
.failureHandler((req, res, ex) -> {
String code = (ex instanceof OAuth2AuthenticationException oae)
? oae.getError().getErrorCode() : "unknown";
res.sendRedirect("/login?error=" + code);
}))
.logout(l -> l
.logoutSuccessUrl("/?logout")
.deleteCookies("JSESSIONID"));
return http.build();
}
}
SecurityFilterChain を自分で定義すると、Boot の自動設定(OAuth2ClientWebSecurityAutoConfiguration)の分は作られなくなります。自動設定の中身は、v4.1.1 のソースでは「すべてのリクエストに認証を求め、oauth2Login と oauth2Client を既定で有効にする」だけです。SecurityFilterChain の基本は、関連記事「Spring Security入門|SecurityFilterChainとDB認証」で扱っています。
failureHandler を書くのには理由があります。 Spring Security 7.1.1 の既定のログイン画面(DefaultLoginPageGeneratingFilter)は、失敗したとき理由にかかわらず Invalid credentials とだけ表示します。上のように getErrorCode() を取り出すと、下の「よくあるエラー」の表で原因を引けます。
ユーザー情報の取り出し
Google ログイン(openid スコープあり)では、ログインした人は OidcUser になります。
package com.example.web;
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("/login")
public String login() {
return "login";
}
@GetMapping("/home")
public String home(@AuthenticationPrincipal OidcUser user, Model model) {
model.addAttribute("sub", user.getSubject()); // Google のユーザー ID(変わらない)
model.addAttribute("email", user.getEmail());
model.addAttribute("verified", user.getEmailVerified());
model.addAttribute("name", user.getFullName());
model.addAttribute("picture", user.getPicture());
model.addAttribute("hd", user.getClaimAsString("hd")); // Google Workspace のドメイン
return "home";
}
}
Google のドキュメントにある、ID トークンの主な項目です。
| 項目 | 取り出し方 | いつ入るか |
|---|---|---|
sub |
getSubject() |
いつも。Google アカウントごとに一意で、再利用されない |
email |
getEmail() |
email スコープのとき。一意とは限らず、変わることもある |
email_verified |
getEmailVerified() |
email スコープのとき |
name |
getFullName() |
必ず入るとは限らない(profile スコープ) |
given_name / family_name |
getGivenName() / getFamilyName() |
同上 |
picture |
getPicture() |
同上 |
locale |
getLocale() |
同上 |
hd |
getClaimAsString("hd") |
Google Workspace などの組織のアカウントのときだけ |
Google のドキュメントでは「email をユーザーを見分けるキーに使わず、sub を使う」と書かれています。 DB でユーザーを探すときも sub を使います。
Thymeleaf の画面では、sec:authentication を使わなくても、上のように Model に入れて表示できます。
<!-- templates/home.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<img th:if="${picture}" th:src="${picture}" width="48" height="48" alt="">
<p th:text="${name} + ' さん'">名前</p>
<p th:text="${email}">メール</p>
<form th:action="@{/logout}" method="post">
<button type="submit">ログアウト</button>
</form>
</body>
</html>
<!-- templates/login.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:if="${param.error}" th:text="'ログインできませんでした(' + ${param.error} + ')'"></p>
<p th:if="${param.logout}">ログアウトしました</p>
<a th:href="@{/oauth2/authorization/google}">Google でログイン</a>
</body>
</html>
ログインのリンク先は /oauth2/authorization/google です(google は registration の名前)。Thymeleaf の属性は、関連記事「Thymeleafの使い方|th:each・th:ifなど属性一覧と出力例」で扱っています。
DB のユーザーと紐づける
ログインのたびに、sub で自分の DB のユーザーを探し、無ければ作ります。あわせて、DB の権限(ロール)をログインした人に付けます。
package com.example.auth;
import jakarta.persistence.*;
import java.time.Instant;
@Entity
@Table(name = "app_user",
uniqueConstraints = @UniqueConstraint(columnNames = {"provider", "provider_subject"}))
public class AppUser {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false) private String provider; // "google"
@Column(name = "provider_subject", nullable = false) private String providerSubject; // sub
private String email;
private String displayName;
@Column(nullable = false) private String role = "USER";
private Instant lastLoginAt;
protected AppUser() {}
public AppUser(String provider, String providerSubject) {
this.provider = provider;
this.providerSubject = providerSubject;
}
// getter・setter は省略
}
package com.example.auth;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AppUserRepository extends JpaRepository<AppUser, Long> {
Optional<AppUser> findByProviderAndProviderSubject(String provider, String providerSubject);
}
package com.example.auth;
import java.time.Instant;
import java.util.List;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AppOidcUserService extends OidcUserService {
private final AppUserRepository users;
public AppOidcUserService(AppUserRepository users) {
this.users = users;
}
@Override
@Transactional
public OidcUser loadUser(OidcUserRequest request) throws OAuth2AuthenticationException {
OidcUser google = super.loadUser(request); // ID トークンとユーザー情報を取る
// 例:社内ドメインだけ許可する(hd は ID トークンで確かめる)
if (!"example.com".equals(google.getClaimAsString("hd"))) {
throw new OAuth2AuthenticationException(new OAuth2Error("domain_not_allowed"));
}
String provider = request.getClientRegistration().getRegistrationId(); // "google"
AppUser user = users.findByProviderAndProviderSubject(provider, google.getSubject())
.orElseGet(() -> new AppUser(provider, google.getSubject()));
user.setEmail(google.getEmail());
user.setDisplayName(google.getFullName());
user.setLastLoginAt(Instant.now());
users.save(user);
var authorities = List.of(new SimpleGrantedAuthority("ROLE_" + user.getRole()));
return new DefaultOidcUser(authorities, google.getIdToken(), google.getUserInfo(), "sub");
}
}
| 決めごと | 理由 |
|---|---|
provider と sub の組で一意にする |
後から GitHub などを足しても、ID がぶつからない |
| メールアドレスで探さない | Google のドキュメントで、メールは一意とは限らず変わりうるとされている |
| 権限は DB から付ける | Google の情報には、アプリの権限は入っていない |
ドメインの制限は hd をサーバーで確かめる |
認可リクエストに hd を付けても、それは画面の候補をしぼるだけ |
既存の「メールアドレスとパスワード」の会員と紐づけたいときは、ログイン中の会員が「Google と連携」ボタンを押したときに sub を保存する形にします。メールアドレスが同じというだけで自動で結びつけると、メールの確認状態によっては、別人のアカウントに入れてしまうおそれがあります。
ログアウト
/logout に POST すると、アプリのセッションが消えます。CSRF 対策が有効なので、GET のリンクではなく、上の Thymeleaf のようにフォームで送ります(Thymeleaf の th:action は CSRF トークンを自動で入れます)。
| ログアウトの範囲 | 方法 | Google で |
|---|---|---|
| アプリだけ | /logout に POST |
できる。Google にはログインしたまま |
| ID プロバイダー(IdP)も一緒に | OidcClientInitiatedLogoutSuccessHandler |
Google の Discovery ドキュメントに end_session_endpoint が無いので、この形にはならない |
| アプリの連携そのものを解除 | https://oauth2.googleapis.com/revoke にトークンを POST |
できる(同意を取り消す) |
Spring Security 7.1.1 のソースでは、OidcClientInitiatedLogoutSuccessHandler は、プロバイダーの設定に end_session_endpoint があるときだけ、そこへ移します。無いときは、ふつうの logoutSuccessUrl へ戻ります。Google の場合、アプリのログアウト後に「Google でログイン」を押すと、Google 側はまだログインしているので、すぐ戻ってきます。別のアカウントに切り替えたい人のために、上のコードでは prompt=select_account を付けています。 Google のドキュメントでは、prompt の値は none・consent・select_account です。
Keycloak など end_session_endpoint を持つ IdP では、IdP のログアウトまで行えます。関連記事「Keycloak入門|OIDCログインとJWT検証を最短で構築」で扱っています。
よくあるエラー
Google の画面に出るエラー
Google のドキュメント(ウェブサーバー アプリケーション向け OAuth 2.0)に載っているエラーです。
| エラー | 意味 | 直し方 |
|---|---|---|
redirect_uri_mismatch |
認可リクエストの redirect_uri が、クライアント ID に登録した URI と一致しない |
下の「redirect_uri_mismatch の原因」 |
invalid_client |
クライアント シークレットが正しくない | ID とシークレットの組を確かめる |
deleted_client |
クライアントが削除された(使われていないため自動で削除されることもある) | 30日以内なら復元できる。無理なら作り直す |
org_internal |
プロジェクトが特定の組織のアカウントだけに限られている | 対象を「外部」にするか、組織のアカウントで入る |
admin_policy_enforced |
Google Workspace の管理者のポリシーでスコープが止められている | 管理者にクライアント ID を許可してもらう |
disallowed_useragent |
アプリ内ブラウザ(WebView)から開いた | 端末の標準ブラウザで開く |
invalid_request |
リクエストの形が正しくない・必要なパラメータが無い | scope・response_type などの設定を確かめる |
redirect_uri_mismatch の原因
| 送られた URI | 登録した URI | 原因 |
|---|---|---|
http://app.example.com/login/oauth2/code/google |
https://app.example.com/… |
プロキシの後ろで、アプリが自分を http だと思っている |
http://127.0.0.1:8080/… |
http://localhost:8080/… |
ホスト名の違い |
http://localhost:8081/… |
http://localhost:8080/… |
ポートの違い |
…/login/oauth2/code/google-login |
…/login/oauth2/code/google |
registration の名前を変えた |
https://example.com/myapp/login/… |
https://example.com/login/… |
コンテキストパスの付け忘れ |
…/google/ |
…/google |
末尾のスラッシュ |
いちばん多いのは1行目です。リダイレクト URI の {baseUrl} は、アプリが受け取ったリクエストから組み立てられます。nginx やロードバランサーで https を終端していると、アプリには http で届くので、http://… が Google に送られます。server.forward-headers-strategy: native(Tomcat などの組み込みサーバーで X-Forwarded-Proto を読む)か framework を設定し、プロキシ側で X-Forwarded-Proto と X-Forwarded-Host を渡します。どうしても合わないときは、redirect-uri に固定の URI を書く方法もあります。
spring:
security:
oauth2:
client:
registration:
google:
redirect-uri: "https://app.example.com/login/oauth2/code/{registrationId}"
Spring 側のエラー(ログ・failureHandler で見えるもの)
Spring Security 7.1.1 のソースにあるエラーコードです。OAuth2Error の toString() は [コード] 説明 の形なので、DEBUG ログにはこの形で出ます。
| エラーコード | 出る場面 | よくある原因 |
|---|---|---|
authorization_request_not_found |
Google から戻ったとき、保存しておいた認可リクエストがセッションに無い | 行きと帰りでホスト名が違う(localhost と 127.0.0.1)、複数台でセッションを共有していない、戻るのに時間がかかりセッションが切れた |
invalid_state_parameter |
戻ってきた state が保存した値と違う |
ログインのタブを2つ開いた、前に開いたタブで戻った |
invalid_token_response |
code をトークンに交換するのに失敗した |
シークレットの誤り(Google の invalid_client)、サーバーから Google へ出られない(プロキシ・ファイアウォール) |
invalid_id_token |
ID トークンの中身が正しくない | サーバーの時計のずれ(exp・iat)、client-id の誤り(aud) |
invalid_nonce |
ID トークンの nonce が違う |
同上(同時に複数のログイン) |
client_registration_not_found |
/login/oauth2/code/xxx の xxx が設定に無い |
URL と registration の名前の不一致 |
invalid_request |
戻ってきた URL に code も error も無い |
戻り先の URL を直接開いた |
access_denied(Google から) |
利用者が同意を拒否した | — |
invalid_token_response の説明文は、ソースでは An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: の後ろに、通信の例外のメッセージを付けた形です。後ろの部分に Google の応答(invalid_client など)や Connection refused が入るので、そこで原因を分けます。
起動時のエラー(Spring Boot 4.1.1 のソース)
| メッセージ | 原因 |
|---|---|
Client id of registration 'google' must not be empty. |
client-id が空(環境変数が渡っていない) |
Provider ID must be specified for client registration 'google-login' |
registration の名前が google 以外で、provider: が無い |
Unknown provider ID 'gogle' |
provider: の綴りの誤り |
よくある質問
Q. OAuth2User と OidcUser のどちらで受け取りますか。
A. スコープに openid が入っていれば OidcUser です。Google の既定のスコープには openid が入っています。GitHub のように OpenID Connect でないプロバイダーと共通で扱うなら、親の型の OAuth2User で受け取り、getAttribute("…") で項目を読みます。
Q. ログインしたあとに Google の API(カレンダーなど)も呼びたいです。
A. scope に必要なスコープを足し、@RegisteredOAuth2AuthorizedClient("google") OAuth2AuthorizedClient client でアクセストークンを受け取ります。Google のドキュメントでは、利用者がいないときにも使うリフレッシュトークンは access_type=offline を付けたときに返されます。
Q. REST API(SPA のバックエンド)でも同じ形で使えますか。 A. この記事の形は、サーバーがセッションを持つ画面のアプリ向けです。SPA からトークンを付けて API を呼ぶ形なら、API 側は「リソースサーバー」として JWT を検証します。関連記事「Spring Security JWT認証の実装|Boot 4対応の設定コード全文」で扱っています。
Q. ログイン後に 403 になります。 A. 権限(ロール)が足りないか、CSRF トークンが無い POST です。原因の切り分けは、関連記事「Spring Securityで403になる原因|POSTだけ失敗する時」で扱っています。
まとめ
- 依存は
spring-boot-starter-security-oauth2-client(Boot 4)。registrationをgoogleにするとclient-idとclient-secretだけで動く - リダイレクト URI は
{baseUrl}/login/oauth2/code/google。https・ホスト名・ポート・コンテキストパスまで一致させる - プロキシの後ろでは
server.forward-headers-strategyを設定する - ユーザーは
subで見分ける。メールアドレスをキーにしない - DB との紐づけは
OidcUserServiceを継承して、権限も DB から付ける - ログアウトはアプリのセッションだけ。Google には
end_session_endpointが無い - 既定のログイン画面は理由を出さないので、
failureHandlerでエラーコードを取り出す
参考・出典
確認日はいずれも 2026年10月13日です。
- Spring Security Reference「Core Configuration(OAuth 2.0 Login)」:https://docs.spring.io/spring-security/reference/servlet/oauth2/login/core.html
- Spring Security 7.1.1 ソース(
CommonOAuth2Provider・OAuth2LoginAuthenticationFilter・OidcClientInitiatedLogoutSuccessHandler・DefaultLoginPageGeneratingFilter):https://github.com/spring-projects/spring-security/tree/7.1.1 - Spring Boot v4.1.1 ソース(
spring-boot-security-oauth2-client):https://github.com/spring-projects/spring-boot/tree/v4.1.1 - Google for Developers「Using OAuth 2.0 for Web Server Applications」:https://developers.google.com/identity/protocols/oauth2/web-server
- Google for Developers「OpenID Connect」:https://developers.google.com/identity/openid-connect/openid-connect
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Spring BootでGoogleログイン|OAuth2 Clientの完成コード」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。