该存储库提供了可与Cocoda映射工具一起使用的登录服务器。它允许用户使用不同的提供商(例如github,orcid)进行身份验证。有关如何使用此情况的示例,请参见https://coli-conc.gbv.de/login/api。
.envproviders.jsonapplications.jsonLogin-Server需要Node.js(> = = V18,V20)并访问MongoDB数据库(> = V5,V7推荐)。
git clone https://github.com/gbv/login-server.git
cd login-server
npm install
# after setting up or changing providers, create indexes
npm run indexes也可以通过Docker获得登录服务器。请参阅https://github.com/gbv/login-server/blob/master/docker/dreadme.md上的文档。
如果在反向代理后面运行服务器,请确保包括X-Forwarded-Proto标头,允许所有HTTP方法,并启用Websocket代理。
您需要提供两个配置文件:
.env配置应用程序:
# recommended, port for express, default: 3004
PORT=
# recommended, full base URL, default: http://localhost[:PORT]/
# (required when used in production or behind a reverse proxy)
BASE_URL=
# title of application (will be shown in header)
TITLE=My Login Server
# list of allowed origins separated by comma, includes the hostname of BASE_URL by default
ALLOWED_ORIGINS=
# required for some strategies to enable production mode, default: development
NODE_ENV=production
# strongly recommended, imprint and privacy URLs for footer and clients
IMPRINT_URL=
PRIVACY_URL=
# recommended, secret used by the session
SESSION_SECRET=
# optional, maximum number of days a session is valid (rolling), default: 30
COOKIE_MAX_DAYS=
# threshold in minutes when to send "sessionAboutToExpire" events, default: 60
SESSION_EXPIRATION_MESSAGE_THRESHOLD=
# interval in minutes in which to check for expiring sessions, default: 5
SESSION_EXPIRATION_MESSAGE_INTERVAL=
# username used for MongoDB, default: <empty>
MONGO_USER=
# password used for MongoDB, default: <empty>
MONGO_PASS=
# host used for MongoDB, default: 127.0.0.1
MONGO_HOST=
# port used for MongoDB, default: 27017
MONGO_PORT=
# database used for MongoDB, default: login-server
MONGO_DB=
# the rate limit window in ms, default: 60 * 1000
RATE_LIMIT_WINDOW=
# the rate limit tries, default: 10
RATE_LIMIT_MAX=
# a jsonwebtoken compatible keypair
JWT_PRIVATE_KEY_PATH=
JWT_PUBLIC_KEY_PATH=
# the jsonwebtoken algorithm used
JWT_ALGORITHM=
# expiration time of JWTs in seconds, default: 120, min: 10
JWT_EXPIRES_IN=
# URL for Sources, default: https://github.com/gbv/login-server
SOURCES_URL=
# the path to the providers.json file, default: ./providers.json
PROVIDERS_PATH=
# log = log all messages, warn = only log warnings and errors, error = only log errorsl default: log
VERBOSITY=providers.json配置提供商。参见提供者。
applications.json为了向用户提供有关哪些应用程序访问其数据的信息,哪些应用程序启动了会话的登录名,您可以在applications.json中提供应用程序列表。该列表必须是一系列对象,每个对象都需要具有url和name 。例子:
[
{
"url" : " https://bartoc.org " ,
"name" : " BARTOC "
},
{
"url" : " https://coli-conc.gbv.de/coli-rich/ " ,
"name" : " coli-rich "
},
{
"url" : " https://coli-conc.gbv.de/cocoda/app/ " ,
"name" : " Cocoda "
},
{
"url" : " https://coli-conc.gbv.de/cocoda/dev/ " ,
"name" : " Cocoda (dev) "
},
{
"url" : " https://coli-conc.gbv.de/cocoda/rvk/ " ,
"name" : " Cocoda (RVK) "
},
{
"url" : " https://coli-conc.gbv.de/cocoda/wikidata/ " ,
"name" : " Cocoda (Wikidata) "
},
{
"url" : " https://coli-conc.gbv.de/cocoda/ " ,
"name" : " Cocoda (other) "
},
{
"url" : " https://coli-conc.gbv.de " ,
"name" : " Other coli-conc application "
}
]应该访问URL,因为接口将链接到它。会话与应用程序的推荐子URL包含应用程序的url相关联。应用程序将从上到底检查,因此您应该从最具体的URL订购至最少特定的URL(请参见上面的示例)。
npm run start该服务器提供Web接口,HTTP API和Websocket。
Web界面允许用户创建和管理与身份提供商的多个身份的连接(请参阅提供商)的帐户。提供商用于对用户进行身份验证,因为登录服务器没有存储任何密码(单登录)。
HTTP API和Websocket允许客户端应用程序与登录服务器进行交互,例如,检查用户是否已登录并找出属于用户的身份(请参阅JoavaScript库,请参见login-client和login-client-vue,以使用login-server连接Web应用程序)。
登录服务器可以进一步用于对用户进行对其他服务的身份验证,以便用户可以证明其身份。
目录bin包含用于管理服务器实例的辅助脚本,例如列出用户帐户和管理本地提供商。
测试使用与.env中配置的相同的mongoDB,仅在数据库名称之后的后缀-test中使用。
npm test Login-Server使用Passport(GitHub)作为身份验证中间件。护照使用所谓的“策略”来支持不同提供商的身份验证。可以在此处找到可用策略的列表。目前在登录服务器中支持的策略是:
由于策略在其验证回调中使用不同的参数,因此每个策略在文件夹strategies/中都有自己的包装文件。要在登录服务器中添加另一种策略,请添加一个名为{name}.js (其中{name}文件是与passport.authenticate一起使用的策略的名称),其中包括以下结构(github作为例如):
/**
* OAuth Stategy for GitHub.
*/
// Import strategy here
import { Strategy } from "passport-github"
// Don't change this part!
export default ( options , provider , callback ) => new Strategy ( options ,
// Strategies have different callback parameters.
// `req` is always the first and the `done` callback is always last.
( req , token , tokenSecret , profile , done ) => {
// Prepare a standardized object for the user profile,
// usually using information from the `profile` parameter
let providerProfile = {
// Required, don't change this!
provider : provider . id ,
// Required: Choose a field that represents a unique user ID for this user
id : profile . id ,
// Optional: Provides a display name (e.g. full name)
name : profile . displayName ,
// Optional: Provides a username
username : profile . username
}
// Call a custom callback. `req`, `providerProfile`, and `done` are required,
// `token` and `tokenSecret` can be null.
callback ( req , token , tokenSecret , providerProfile , done )
} )您可以将现有策略视为示例,并通过拉动请求添加您自己的策略。
添加策略后,您可以通过将提供商添加到providers.json 。
[
{
"id" : " github " ,
"strategy" : " github " ,
"name" : " GitHub " ,
"template" : " https://github.com/{username} " ,
"options" : {
"clientID" : " abcdef1234567890 " ,
"clientSecret" : " abcdef1234567890abcdef1234567890 "
},
"image" : " https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg " ,
"url" : " https://github.com "
}
]提供商列表中的每个对象都可以具有以下属性:
id (必需) - 提供商的唯一ID。strategy (必需) - 提供商使用的护照策略的名称。name (必需) - 提供商的名称。template (可选) - 生成URI的模板字符串(占位符{field}可以是providerProfile对象中提供的任何字段,通常是{id}或{username} )。credentialsNecessary (可选) - 如果该提供商需要用户名和密码凭据,则将其设置为true 。 Login-Server将不是重定向(对于OAuth),而是将显示登录表格,该表格将将凭据发送到端口端点。options (主要是必需的) - 该策略的选项对象,通常包含身份验证端点的客户端凭证。image (可选) - 与提供商关联的图像。将显示在登录页面和连接的身份列表中。您可以在文件夹static/中提供静态图像。然后,该属性的值将为static/myimage.svg 。如果文件名与提供商的id匹配,则图像将自动关联。url (可选) - 提供商的URL;将在其图像 /图标下/account上链接。策略github , orcid , mediawiki和stackexchange有默认URL。以下是一个示例providers.json显示如何配置每个现有提供商:
[
{
"id" : " github " ,
"strategy" : " github " ,
"name" : " GitHub " ,
"template" : " https://github.com/{username} " ,
"options" : {
"clientID" : " abcdef1234567890 " ,
"clientSecret" : " abcdef1234567890abcdef1234567890 "
}
},
{
"id" : " orcid " ,
"strategy" : " orcid " ,
"name" : " ORCID " ,
"template" : " https://orcid.org/{id} " ,
"options" : {
"clientID" : " APP-abcdef1234567890 " ,
"clientSecret" : " abcdef1-23456-7890ab-cdef12-34567890 "
}
},
{
"id" : " mediawiki " ,
"strategy" : " mediawiki " ,
"name" : " Mediawiki " ,
"template" : " https://www.mediawiki.org/wiki/User:{username} " ,
"options" : {
"consumerKey" : " abcdef1234567890 " ,
"consumerSecret" : " abcdef1234567890abcdef1234567890 "
}
},
{
"id" : " stackexchange " ,
"strategy" : " stackexchange " ,
"name" : " Stack Exchange " ,
"template" : " https://stackexchange.com/users/{id} " ,
"options" : {
"clientID" : " 12345 " ,
"clientSecret" : " abcdef1234567890(( " ,
"stackAppsKey" : " 1234567890abcdefg(( "
}
},
{
"id" : " my-ldap " ,
"strategy" : " ldapauth " ,
"name" : " My LDAP " ,
"credentialsNecessary" : true ,
"options" : {
"server" : {
"url" : " ldap://ldap.example.com " ,
"bindDN" : " uid=admin,dc=example,dc=com " ,
"bindCredentials" : " abcdef1234567890 " ,
"searchBase" : " dc=example,dc=com " ,
"searchFilter" : " (uid={{username}}) "
}
}
},
{
"id" : " easydb " ,
"name" : " easydb test provider " ,
"strategy" : " easydb " ,
"credentialsNecessary" : true ,
"options" : {
"url" : " https://easydb5-test.example.com/api/v1/ "
}
},
{
"id" : " some-script " ,
"strategy" : " script " ,
"name" : " Some Script " ,
"credentialsNecessary" : true ,
"template" : " https://example.org/some-script/{id} " ,
"options" : {
"script" : " ./bin/example-script "
}
},
{
"id" : " cbs " ,
"strategy" : " cbs " ,
"name" : " CBS " ,
"credentialsNecessary" : true ,
"template" : " cbs:{id} " ,
"options" : {
"url" : " https://example.com/ext/api/colirich/users/info " ,
"apiKey" : " abcdef1234567890 "
}
}
]要配置本地提供商,请在bin/manage-local.js下使用提供的脚本。它将允许您创建/删除本地提供商,并为本地提供商创建/删除用户。
您可以在.env中使用providers.json调整提供PROVIDERS_PATH的路径。
有关使用MediaWiki提供商的注释:
"baseURL": "https://www.wikidata.org/" 。https://coli-conc.gbv.de/login/login/wikidata/return以获取我们的登录名字实例)。有关使用脚本提供商的注释:
lib/script-strategy.js )。options.script中提供)可以相对于登录服务器的根文件夹,也可以是绝对路径(建议用于Docker)。bin/example-script中找到。chmod +x )。id值。可选地,可以提供name ,并将用作显示名称。Login-Server提供JSON Web令牌,可用于针对其他服务(例如JSKOS-Server)进行身份验证。 jsonwebtoken用于签名令牌。
默认情况下,当应用程序首次启动时(2048位,使用node-rsa),将生成一个新的RSA键盘。默认情况下,该生成的键盘将在./private.key和./public.key中可用。您可以将./public.key文件提供给需要验证令牌的任何其他服务。或者,当前使用的公钥在 /关于端点上提供。
您还可以通过在.env中设置JWT_PRIVATE_KEY_PATH和JWT_PUBLIC_KEY_PATH来提供密钥文件的自定义路径。如果找不到一个或两个键,将生成键。默认情况下,使用RS256算法,但是可以通过设置JWT_ALGORITHM使用任何其他公共密钥算法。
默认情况下,每个令牌有效期为120秒。您可以通过在.env中设置JWT_EXPIRES_IN来调整此问题。
通过 /令牌端点或使用Type token的Websocket请求将接收令牌。此外,在用户登录后,然后在最后一个令牌到期之前定期通过Websocket发送令牌。
示例如何验证令牌:
import jwt from "jsonwebtoken"
// token, e.g. from user request
let token = "..."
// get public key from file or endpoint
let publicKey = "..."
jwt . verify ( token , publicKey , ( error , decoded ) => {
if ( error ) {
// handle error
// ...
} else {
let { user , iat , exp } = decoded
// user is the user object
// iat is the issued timestamp
// exp is the expiration timestamp
// ...
}
} )另外,您可以使用Passport-JWT(示例将如下)。
显示一个登陆页面,其中包含有关登录服务器的一般信息。
显示一个网站来管理一个人的用户帐户(如果已经进行了认证)或重定向到/login (如果未进行身份验证)。
显示一个网站,以管理用户的会话(如果已进行身份验证)或重定向到/login (如果未进行身份验证)。
显示一个网站登录(如果未进行身份验证)或直接到/account (如果已进行身份验证)。
如果给出了查询参数redirect_uri ,则该站点将在成功登录后重定向到指定的URI。 (如果给出了参数但为空,则将使用转介器作为URI。)
显示提供商的登录页面。对于OAuth提供商,此页面将重定向到提供商的页面以连接您的身份,然后将其重定向到/login/:provider/return 。对于使用凭据的提供商,这将显示登录表格。
此页面还处理redirect_uri (请参见上面的/login )。
使用凭据的提供商的端点。如果成功,它将重定向到/account ,否则它将返回/login/:provider 。
将提供商与用户断开连接,并将其重定向到/account 。
将用户从其帐户中记录下来。请注意,由于将其用于Websocket,因此将其保留。这使应用程序可以将事件发送到当前会话的活动Websocket,即使用户已登录。
显示一个网站以删除一个人的用户帐户。
将用户帐户删除并重定向到/login 。
该服务器为每个OAuth提供商提供了OAuth重定向端点(重定向URI)。
OAuth请求的回调端点。将将所连接的身份保存到用户(或者必要时创建新用户),然后将其重定向到/account 。
在直接针对HTTP API和WebSocket API进行编程之前,请查看登录 - 委托JavaScript浏览器库。可以在此处看到它(该站点的来源)。
返回带有键title (登录服务器实例的标题), env (如development或production环境), publicKey (通常是RSA公共密钥)和algorithm (使用的JSONWEBTOKEN算法)的对象。签署JWT时,使用给定公共密钥的相应私钥。
返回可用提供商的列表(删除敏感信息)。
返回当前登录的用户。没有登录用户时返回404错误。
返回特定用户。目前仅限于自己的用户ID。
调整特定用户。仅当当前登录同一用户时才能使用。允许属性更改: name (其他所有内容都将被忽略)。
除当前会话外,除了当前用户外,还要删除当前用户的所有会话。
使用SessionID :id删除会话(需要是当前用户的会话)。
以格式返回JSON Web令牌:
{
"token" : " <JWT> " ,
"expiresIn" : 120
}另请参阅:JWTS。
令牌本身将包含一个user属性(该属性包含有关当前登录的用户的信息,或者如果未登录用户,则为null)和在WebSocket连接中进行身份验证所需的sessionID属性。
基本URL /发送有关当前用户或会话的事件的WebSocket API。事件以JSON编码的字符串发送,看起来像这样:
{
"type" : " event name (see below) " ,
"date" : " date (as ISOString) " ,
"data" : {
"user" : {
"uri" : " URI of user " ,
"name" : " name of user " ,
"identities" : {
"xzy" : {
"id" : " ID of user for provider xzy " ,
"uri" : " URI or profile URL of user for provider xzy " ,
"name" : " display name of user for provider xzy (if available) " ,
"username" : " username of user for provider xzy (if available) "
}
}
}
}
}open - 在建立WebSocket连接后发送,使用此而不是ws.onopen !loggedIn用户登录时发送(如果用户已经登录,将在建立Websocket后立即发送)loggedOut - 在用户登录时发送(如果未登录用户,将在建立Websocket后立即发送)updated - 在更新用户时发送(例如,添加了新的身份等)providers - 建立WebSocket连接后发送(由属性data.providers组成。about在建立WebSocket连接后发送(属性data将与get /aid中的格式相同)token - 当用户登录时发送,然后在以前的令牌到期之前以间隔(属性data格式与get /token中的格式)进行登录时发送)authenticated - 在请求身份验证时作为成功答复发送(请参阅下文)pong作为ping类型请求的答案发送(可用于确定Websocket是否已建立)sessionAboutToExpire当当前关联的会话即将到期时发送error - 通过Websocket作为对畸形消息的答案发送(由属性data.message组成。带有错误消息的消息)您也可以将请求发送到Websocket。这些也必须是以下形式编码的JSON编码的字符串:
{
"type" : " name of request "
}这是一个特殊请求,使用从get /令牌获得的JWT将当前Websocket与特定会话相关联(已发送请求对象需要属性token )
当与登录服务器不同的域使用Websocket时,有时需要authenticate请求。在这种情况下,需要通过API请求令牌(例如,使用选项credentials: "include"或axios withCredentials: true ),并通过Websocket发送。令牌包括加密的sessionID,然后将与WebSocket连接关联。这是一个有关Web应用程序的工作流程的示例:https://coli-conc.gbv.de/login/api
以下是有关如何连接到Websocket的一个简单示例。
// Assumes server is run on localhost:3005
let socket = new WebSocket ( "ws://localhost:3005" )
socket . addEventListener ( "message" , ( message ) => {
try {
let event = JSON . parse ( message )
alert ( event . event , event . user && event . user . uri )
} catch ( error ) {
console . warn ( "Error parsing WebSocket message" , message )
}
} ) 公关接受。
dev分支为基础。 dev的更改将仅用于新版本的master 。仅适用于维护者
在开发过程中,请在dev部门上工作(或者更好,在功能分支中开发,并在准备就绪时合并成dev )。
当准备就绪新版本时(即功能完成,合并到dev ,所有测试成功)时,请运行随附的发行脚本(如有必要,用“次要”或“ MARIAD”替换):
npm run release:patch这将:
dev上dev是最新的npm version patch (或“次要”/“ Major”)devmasterdev合并变化masterdev运行此操作后,GitHub操作将自动创建新的GitHub发行草稿。请手动编辑并发布该版本。
MIT©2019 Verbundzentrale des GBV(VZG)