OpenID Connect authorization
This UnityBase model implements authentication over OpenID Connect.
For users: Authorization Code Flow
Users from browsers can be authenticated using OpenID Authorization Code Flow
- https://tools.ietf.org/html/rfc6749#section-4.1
- https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow
For adminUI "OpenIDConnect" should be added to the "authenticationMethods".
Configuration:
"security": {
"authenticationMethods": ["UB", "OpenIDConnect"]
}
Usage:
const openID = require('@unitybase/openid-connect')
let oIdEndPoint = openID.registerEndpoint('openIDConnect')
// Google
// see https://accounts.google.com/.well-known/openid-configuration to get Url`s
oIdEndPoint.registerProvider('Google', {
authUrl: 'https://accounts.google.com/o/oauth2/auth',
tokenUrl: 'https://accounts.google.com/o/oauth2/token',
userInfoUrl: 'https://www.googleapis.com/oauth2/v1/userinfo',
userInfoHTTPMethod: 'GET',
scope: 'openid',
nonce: '123',
response_type: 'code',
client_id: '350085411136-lpj0qvr87ce0r0ae0a3imcm25joj2t2o.apps.googleusercontent.com',
client_secret: 'dF4qmUxhHoBAj-E1R8YZUCqA',
getOnFinishAction: function (response) {
return 'opener.$App.onFinishOpenIDAuth(' + JSON.stringify(response) + '); close();'
},
getUserID: function(userInfo) {
let inst = UB.Repository('uba_user').attrs(['ID'])
.where('[name]', '=', userInfo.id).select()
return inst.eof ? null : inst.get('ID')
}
})
// Hideez
oIdEndPoint.registerProvider('Hideez', {
authUrl: 'https://xxx.hideez.com/connect/authorize',
tokenUrl: 'https://xxx.hideez.com/connect/token',
userInfoUrl: 'https://xxx.hideez.com/connect/userinfo',
userInfoHTTPMethod: 'GET',
scope: 'openid email', //email - omportant
//scope: 'openid email phone roles profile',
nonce: 'replaceToSomeRandom',
response_type: 'code',
client_id: '.....',
client_secret: '....',
getUserID: function(userInfo) {
let inst = UB.Repository('uba_user').attrs(['ID'])
.where('[name]', '=', (userInfo.email || '-').toLocaleLowerCase()).select().
return inst.eof ? null : inst.get('ID')
}
})
// Azure
// see https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration to get Url`s
oIdEndPoint.registerProvider('Azure', {
authUrl: 'https://login.microsoftonline.com/{tenant-guid}/oauth2/v2.0/authorize',
tokenUrl: 'https://login.microsoftonline.com/{tenant-guid}/oauth2/v2.0/token',
userInfoUrl: 'https://graph.microsoft.com/oidc/userinfo',
userInfoHTTPMethod: 'POST',
scope: 'openid',
nonce: '123',
response_type: 'code',
response_mode: 'query',
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
getUserID: function(userInfo) {
// console.debug("userinfo=", JSON.stringify(userInfo))
let inst = UB.Repository('uba_user').attrs(['ID'])
.where('[name]', '=', userInfo.name).select()
console.debug("user", inst.eof ? null : inst.get('ID'))
return inst.eof ? null : inst.get('ID')
}
})
For Machine2Machine
To communicate between UnityBase server and other services, what uses OpenID first - register a provider, for example
for keyCloak
:
const openID = require('@unitybase/openid-connect')
const keyCloakBaseUrl = 'http://localhost:8080/realms/myrealm/protocol/openid-connect'
openID.registerProvider('keyCloak', {
authUrl: keyCloakBaseUrl + '/auth',
tokenUrl: keyCloakBaseUrl + '/token',
userInfoUrl: keyCloakBaseUrl + '/userinfo',
logoutUrl: keyCloakBaseUrl + '/logout',
client_id: 'oidKeycloak',
client_secret: 'CLkwDlhcHGIwFh52HbDJF0mPk1jSdHYa',
userInfoHTTPMethod: 'POST',
scope: 'openid',
nonce: '',
response_type: 'code',
response_mode: 'query'
})
and then use one of available methods to get an Aunthorisation
header value for your API calls
Client Credentials Flow
- https://tools.ietf.org/html/rfc6749#section-4.4
- https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow
Clients Credentials grant
type must be enabled on OpenID provider side ("Service accounts roles" for KeyCloak provider)
const authVal = openID.provider('keyCloak').getCCToken()
UB.get('https://some.server/with/auth', {
headers: {
Authorization: authVal
}
})
Resource Owner Password Flow
username
and password
MUST be stored in secure way on server. NEVER pass this values from client
const authVal = openID.provider('keyCloak').getROPToken(username, password)
UB.get('https://some.server/with/auth', {
headers: {
Authorization: authVal
}
})
Methods
# openIDConnectEp (req: THTTPRequest, resp: THTTPResponse) inner
OpenID Authorization Code Flow
(user interaction) endpoint implementation
- https://tools.ietf.org/html/rfc6749#section-4.1
- https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow
If called as /endpoint - return a list of registered openIDConnect providers, If called as /endpoint/provider:
- without parameters or with mode === 'auth' - redirect to provider
authUrl
- with parameters
code
andstate
- call doProviderAuthHandshake method - with parameters
logout
- redirect to log out url
Arguments:
req
: THTTPRequestresp
: THTTPResponse
# provider (providerName: string) → OpenIdProvider | undefined inner
Return provider by name
Arguments:
providerName
: string
# registerOpenIDEndpoint (endpointName: string) → openIDEndpoint inner
Register openID connect endpoint. In case endpoint already registered - return existed
Return:
endpoint
Arguments:
endpointName
: string
# registerOpenIDProvider (name: string, providerConfig: ProviderConfig) inner
Register OpenID provider
Arguments:
name
: stringproviderConfig
: ProviderConfig
Types
# openIDEndpoint inner
OpenID endpoint. Able to register providers
Properties
registerProvider
: function