2.3. Node.js 어댑터
Red Hat Single Sign-On은 서버 측 JavaScript 애플리케이션을 보호하기 위해 Connect 에 구축된 Node.js 어댑터를 제공합니다. 이 목표는 Express.js 와 같은 프레임워크와 통합할 수 있을 만큼 유연해야 했습니다.
Node.js 어댑터를 사용하려면 먼저 Red Hat Single Sign-On 관리 콘솔에서 애플리케이션의 클라이언트를 생성해야 합니다. 어댑터는 공용, 기밀, 전달자 전용 액세스 유형을 지원합니다. 선택할 수 있는 항목은 사용 사례에 따라 다릅니다.
클라이언트가 생성되면 설치 탭을 클릭하고 형식 옵션 용으로 Red Hat Single Sign-On OIDC JSON 을 선택한 다음 다운로드를 클릭합니다. 다운로드한 keycloak.json 파일은 프로젝트의 루트 폴더에 있어야 합니다.
2.3.1. 설치 링크 복사링크가 클립보드에 복사되었습니다!
Node.js 를 이미 설치했다고 가정하면 애플리케이션의 폴더를 생성합니다.
mkdir myapp && cd myapp
npm init 명령을 사용하여 애플리케이션에 대한 package.json 을 생성합니다. 이제 종속 항목 목록에 Red Hat Single Sign-On 연결 어댑터를 추가합니다.
"dependencies": {
"keycloak-connect": "file:keycloak-connect-18.0.7.tgz"
}
2.3.2. 사용법 링크 복사링크가 클립보드에 복사되었습니다!
- Keycloak 클래스 인스턴스화
-
Keycloak클래스는 애플리케이션과 구성 및 통합을 위한 중앙 지점을 제공합니다. 가장 간단한 생성에는 인수가 포함되지 않습니다.
프로젝트의 루트 디렉터리에서 server.js 라는 파일을 생성하고 다음 코드를 추가합니다.
const session = require('express-session');
const Keycloak = require('keycloak-connect');
const memoryStore = new session.MemoryStore();
const keycloak = new Keycloak({ store: memoryStore });
express-session 종속성을 설치합니다.
npm install express-session
server.js 스크립트를 시작하려면 package.json 의 'scripts' 섹션에 다음 명령을 추가합니다.
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start" "node server.js"
},
이제 다음 명령을 사용하여 서버를 실행할 수 있습니다.
npm run start
기본적으로 이 명령은 애플리케이션의 기본 실행 파일과 함께 keycloak.json 이라는 파일을 찾고 루트 폴더의 경우 공개 키, 영역 이름, 다양한 URL과 같은 키클로크별 설정을 초기화합니다.
이 경우 Keycloak 관리 콘솔에 액세스하려면 Keycloak 배포가 필요합니다.
Podman 또는 Docker를 사용하여 Keycloak 관리 콘솔을 배포하는 방법에 대한 링크를 방문하십시오.
이제 Red Hat Single Sign-On 관리 콘솔 keycloak.json 파일을 가져올 준비가 되었습니다.
다운로드한 파일을 프로젝트의 루트 폴더에 붙여넣습니다.
이 방법을 사용하면 적절한 기본값이 모두 사용됩니다. 또는 keycloak.json 파일 대신 구성 오브젝트를 제공할 수도 있습니다.
const kcConfig = {
clientId: 'myclient',
bearerOnly: true,
serverUrl: 'http://localhost:8080/auth',
realm: 'myrealm',
realmPublicKey: 'MIIBIjANB...'
};
const keycloak = new Keycloak({ store: memoryStore }, kcConfig);
애플리케이션은 다음을 사용하여 사용자를 선호하는 ID 공급자로 리디렉션할 수도 있습니다.
const keycloak = new Keycloak({ store: memoryStore, idpHint: myIdP }, kcConfig);
- 웹 세션 저장소 구성
-
웹 세션을 사용하여 인증을 위해 서버 측 상태를 관리하려면 최소
store매개변수로Keycloak(…)을 초기화하고express-session이 사용되는 실제 세션 저장소를 전달해야 합니다.
const session = require('express-session');
const memoryStore = new session.MemoryStore();
// Configure session
app.use(
session({
secret: 'mySecret',
resave: false,
saveUninitialized: true,
store: memoryStore,
})
);
const keycloak = new Keycloak({ store: memoryStore });
- 사용자 정의 범위 값 전달
-
기본적으로 범위 값
openid는 Red Hat Single Sign-On의 로그인 URL에 쿼리 매개변수로 전달되지만 사용자 지정 값을 추가할 수 있습니다.
const keycloak = new Keycloak({ scope: 'offline_access' });
2.3.3. 미들웨어 설치 링크 복사링크가 클립보드에 복사되었습니다!
인스턴스화한 후 연결 가능 앱에 미들웨어를 설치합니다.Once instantiated, install the middleware into your connect-able app:
이렇게 하려면 먼저 Express를 설치해야 합니다.
npm install express
아래에 설명된 대로 프로젝트에 Express가 필요합니다.
const express = require('express');
const app = express();
아래 코드에 추가하여 Express에서 Keycloak 미들웨어를 구성합니다.
app.use( keycloak.middleware() );
마지막으로 다음 코드를 main.js 에 추가하여 포트 3000에서 HTTP 요청을 수신하도록 서버를 설정해 보겠습니다.
app.listen(3000, function () {
console.log('App listening on port 3000');
});
2.3.4. 프록시 구성 링크 복사링크가 클립보드에 복사되었습니다!
애플리케이션이 SSL 연결 Express를 종료하는 프록시 뒤에서 실행중인 경우 프록시 뒤의 표현 가이드에 따라 SSL 연결을 구성해야 합니다. 잘못된 프록시 설정을 사용하면 잘못된 리디렉션 URI가 생성될 수 있습니다.
설정 예:
const app = express();
app.set( 'trust proxy', true );
app.use( keycloak.middleware() );
2.3.5. 인증 확인 링크 복사링크가 클립보드에 복사되었습니다!
리소스에 액세스하기 전에 사용자가 인증되었는지 확인하려면 keycloak.checkSso() 를 사용합니다. 이는 사용자가 이미 로그인한 경우에만 인증됩니다. 사용자가 로그인하지 않은 경우 브라우저가 원래 요청된 URL로 다시 리디렉션되고 인증되지 않은 상태로 유지됩니다.
app.get( '/check-sso', keycloak.checkSso(), checkSsoHandler );
2.3.6. 리소스 보호 링크 복사링크가 클립보드에 복사되었습니다!
- 간단한 인증
-
리소스에 액세스하기 전에 사용자를 인증해야 하는 것을 강제 적용하려면
keycloak.protect()의 인수 없음 버전을 사용하십시오.
app.get( '/complain', keycloak.protect(), complaintHandler );
- 역할 기반 권한 부여
- 현재 앱의 애플리케이션 역할로 리소스를 보호하려면 다음을 수행합니다.
app.get( '/special', keycloak.protect('special'), specialHandler );
다른 앱의 애플리케이션 역할로 리소스를 보호하려면 다음을 수행합니다.
app.get( '/extra-special', keycloak.protect('other-app:special'), extraSpecialHandler );
영역 역할을 사용하여 리소스를 보호하려면 다음을 수행합니다.
app.get( '/admin', keycloak.protect( 'realm:admin' ), adminHandler );
- 리소스 기반 권한 부여
-
리소스 기반 권한 부여를 사용하면 Keycloak에 정의된 정책 세트를 기반으로 리소스를 보호하고 특정 메서드/작업,** *를 사용하여 애플리케이션에서 권한을 외부화할 수 있습니다. 이를 위해 리소스를 보호하는 데 사용할 수 있는
keycloak.enforcer메서드를 노출합니다.*
app.get('/apis/me', keycloak.enforcer('user:profile'), userProfileHandler);
keycloak-enforcer 방법은 response_mode 구성 옵션의 값에 따라 두 가지 모드에서 작동합니다.
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), userProfileHandler);
response_mode 가 토큰 으로 설정된 경우 애플리케이션에 전송된 전달자 토큰이 나타내는 주체를 대신하여 권한을 서버에서 가져옵니다. 이 경우 서버가 부여한 권한으로 Keycloak에서 새 액세스 토큰을 발행합니다. 서버가 예상 권한으로 토큰을 사용하여 응답하지 않으면 요청이 거부됩니다. 이 모드를 사용하는 경우 다음과 같이 요청에서 토큰을 가져올 수 있습니다.
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), function (req, res) {
const token = req.kauth.grant.access_token.content;
const permissions = token.authorization ? token.authorization.permissions : undefined;
// show user profile
});
애플리케이션이 세션을 사용하고 있고 서버의 이전 결정을 캐시하고 새로 고침 토큰을 자동으로 처리하려는 경우 이 모드를 선호합니다. 이 모드는 클라이언트 및 리소스 서버 역할을 하는 애플리케이션에 특히 유용합니다.
response_mode 가 권한 (기본 모드)로 설정된 경우 서버는 새 액세스 토큰을 발행하지 않고 부여된 권한 목록만 반환합니다. 새 토큰을 발행하지 않는 것 외에도 이 방법은 다음과 같이 요청을 통해 서버에서 부여한 권한을 노출합니다.
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'permissions'}), function (req, res) {
const permissions = req.permissions;
// show user profile
});
사용 중인 response_mode 에 관계없이 keycloak.enforcer 방법은 먼저 애플리케이션에 전송된 전달자 토큰 내의 권한을 확인하려고 합니다. 전달자 토큰이 이미 예상 권한을 전달한 경우 결정을 받기 위해 서버와 상호 작용할 필요가 없습니다. 이 기능은 클라이언트가 보안 리소스에 액세스하기 전에 예상 권한으로 서버에서 액세스 토큰을 가져올 수 있으므로 증분 권한과 같은 Keycloak 인증 서비스에서 제공하는 일부 기능을 사용할 수 있고 keycloak.enforcer 가 리소스에 대한 액세스를 적용하는 경우 서버에 대한 추가 요청을 방지할 수 있는 경우에 특히 유용합니다.
기본적으로 정책 적용자는 애플리케이션에 정의된 client_id 를 사용합니다(예: keycloak.json)을 통해 Keycloak 인증 서비스를 지원하는 Keycloak의 클라이언트를 참조합니다. 이 경우 실제로 리소스 서버인 경우 클라이언트를 공용으로 제공할 수 없습니다.
애플리케이션이 공용 클라이언트(frontend) 및 리소스 서버(backend) 둘 다 역할을 하는 경우 다음 구성을 사용하여 적용하려는 정책과 함께 Keycloak의 다른 클라이언트를 참조할 수 있습니다.
keycloak.enforcer('user:profile', {resource_server_id: 'my-apiserver'})
Keycloak에서 다른 클라이언트를 사용하여 프런트 엔드 및 백엔드를 나타내는 것이 좋습니다.
Keycloak 인증 서비스를 사용하여 보호하는 애플리케이션이 활성화되어 있고 keycloak.json 에 클라이언트 인증 정보가 정의된 경우 추가 클레임을 서버에 푸시하고 정책에서 해당 정보를 정책에서 사용할 수 있도록 할 수 있습니다. 이를 위해 푸시하려는 클레임 과 함께 JSON을 반환하는 함수 를 예상하는 클레임 구성 옵션을 정의할 수 있습니다.
app.get('/protected/resource', keycloak.enforcer(['resource:view', 'resource:write'], {
claims: function(request) {
return {
"http.uri": ["/protected/resource"],
"user.agent": // get user agent from request
}
}
}), function (req, res) {
// access granted
애플리케이션 리소스를 보호하기 위해 Keycloak을 구성하는 방법에 대한 자세한 내용은 인증 서비스 가이드를 참조하십시오.
- 고급 권한 부여
- URL 자체의 일부를 기반으로 리소스를 보호하려면 각 섹션에 대한 역할이 있다고 가정합니다.
function protectBySection(token, request) {
return token.hasRole( request.params.section );
}
app.get( '/:section/:page', keycloak.protect( protectBySection ), sectionHandler );
고급 로그인 설정:
기본적으로 권한이 없는 모든 요청은 클라이언트가 전달하지 않는 한 Red Hat Single Sign-On 로그인 페이지로 리디렉션됩니다. 그러나 기밀 또는 공용 클라이언트는 검색 가능한 API 끝점을 모두 호스팅할 수 있습니다. 인증되지 않은 API 요청에서 리디렉션을 방지하고 대신 HTTP 401을 반환하려면 redirectToLogin 함수를 덮어쓸 수 있습니다.
예를 들어, 이 덮어쓰기는 URL에 /api/가 포함되어 있는지 확인하고 로그인 리디렉션을 비활성화합니다.
Keycloak.prototype.redirectToLogin = function(req) {
const apiReqMatcher = /\/api\//i;
return !apiReqMatcher.test(req.originalUrl || req.url);
};
2.3.7. 추가 URL 링크 복사링크가 클립보드에 복사되었습니다!
- 명시적 사용자 트리거된 로그아웃
-
기본적으로 미들웨어는
/logout에 대한 호출을 따라 Red Hat Single Sign-On-centric 로그아웃 워크플로를 통해 사용자를 전송합니다. 이 설정은logout구성 매개변수를middleware()호출에 지정하여 변경할 수 있습니다.
app.use( keycloak.middleware( { logout: '/logoff' } ));
user-triggered logout이 쿼리 매개변수 redirect_url 을 호출하면 다음을 전달할 수 있습니다.
https://example.com/logoff?redirect_url=https%3A%2F%2Fexample.com%3A3000%2Flogged%2Fout
이 매개변수는 OIDC 로그 아웃 끝점의 리디렉션 URL로 사용되며 사용자는 https://example.com/logged/out 로 리디렉션됩니다.
- Red Hat Single Sign-On 관리자 콜백
-
또한 미들웨어는 Red Hat Single Sign-On 콘솔의 콜백을 지원하여 단일 세션 또는 모든 세션을 로그아웃합니다. 기본적으로 이러한 유형의 관리 콜백은
/의 루트 URL에 대해 발생하지만middleware()호출에admin매개변수를 제공하여 변경할 수 있습니다.
app.use( keycloak.middleware( { admin: '/callbacks' } );
2.3.8. 완료 예 링크 복사링크가 클립보드에 복사되었습니다!
Node.js 어댑터 사용을 사용하는 전체 예제는 Node.js 용 Keycloak 빠른 시작에서 확인할 수 있습니다.