== Securing CubeWerx services for Testbed 12
=== Overview
The purpose of this clause is to describe how CubeWerx plans to provide
authentication and access control on top of its servers deployed for
Testbed 12.
The component of the CubeWerx suite of products that provides authentication
and access control is named the CubeWerx Identity Management System (CubeIMS).
CubeIMS includes an authentication service and a mechanism to define and
control access to content served by CubeWerx OGC web services.
This clause describes how CubeWerx services will be configured to allow
fine-grained access to operations and/or content to users based on the
following types of credentials:
. IP address
. HTTP Basic Authentication
. Distributed Access Control System (DACS)
. CwAuth credentials
For Testbed 12 CubeWerx plans to allow the use of both HTTP Basic
Authentication and CwAuth credentials to provide authentication and
access control.
NOTE: For a description of DACS see https://portal.opengeospatial.org/files/?artifact_id=2253&version=1
=== Use cases
The CwAuth credentials mechanism has the following properties:
. It is secure. CwAuth credentials cannot be spoofed or manipulated. To accomplish this, a PGP public-key encryption mechanism is employed. Credentials can only be authenticated and served by a CubeWerx Authentication Server, and all servers involved can verify the authenticity of a set of credentials by successfully decrypting them with the public key of a known (and trusted) CubeWerx Authentication Server. Furthermore, as long as all connection endpoints are HTTPS, malicious third parties cannot gain access to credentials in transit.
. It is flexible. It is compatible with the various standard distributed-application architectures, including "thin" browser-based clients, hybrid server-side web applications, and "thick" desktop application. It does this by communicating the credentials via an HTTP cookie and documenting how servers and desktop applications should intercept, interpret and propagate this cookie. It is also adaptable to various backend authentication mechanisms.
. It is role-based. In addition to indicating a username (i.e., a specific individual), a set of credentials can also indicate one or more project-defined roles. The access-control rules for a set of services can then be formulated based on these roles, providing a much more natural and flexible mechanism for access control.
. It is cascadable. In a service-chaining scenario (where, for example, a Web Map Server gets its data from a Web Feature Server), CwAuth credentials can be passed down from service to service (as long as they all have the same second-level domain name) so that all entities along the chain are aware of the user's credentials and can control access at each level accordingly.
. It is single sign-on. A user that has logged on to (i.e., received authenticated credentials from) a CubeWerx Authentication Server within a particular domain can then access any server within that domain without having to log in again.
. It is simple. By employing the standard HTTP cookie mechanism and standard public-key encryption technology, the CwAuth credentials mechanism is easy to understand, implement and configure. Unlike DACS, an Apache plugin is not necessary.
. It is efficient. In most situations, once the user has logged in, the various entities never need to contact the authentication server. Validation of credentials is achieved solely by successfully decrypting the credentials cookie with the authentication server's public key (which has been configured beforehand).
One thing that it cannot do is protect files in an online filesystem (which
would require an Apache plugin). It is a service-oriented mechanism only.
=== Mechanism
==== CW_CREDENTIALS cookie
CwAuth credentials are communicated via an HTTP cookie called CW_CREDENTIALS.
Encoded within the value of this cookie is a small XML document containing an
authenticated set of credentials. These credentials are signed with the PGP
private key of a CubeWerx Authentication Server that is set up to provide
authentication for that domain. All other servers within the domain are equipped
with the public key(s) of the trusted authentication server(s) of that domain.
This allows the servers to verify the authenticity of the credentials, since a
successful decryption with the public key of one of the trusted authentication
servers implies that the credentials must have originated from that
authentication server. Note, therefore, that it is not necessary for a server to
contact a CubeWerx Authentication Server in order to decrypt or verify the
authenticity of a set of credentials.
A user is authenticated by making a login request to a CubeWerx Authentication
Server. This can be done directly by having the user visit the CubeWerx
Authentication Server with his/her browser, at which point the user will be
prompted for a username and password. The authentication server will then pass a
CW_CREDENTIALS cookie containing the appropriate credentials back to the browser.
Alternatively, a browser-based application can collect the user's username and
password, and contact the authentication server on behalf of the user (via either an Ajax request or a redirection to the authentication server with a callback
back to the application). Either way, the web browser receives a CW_CREDENTIALS
cookie containing the user's authenticated credentials for that domain.
Since the CwAuth credentials for a particular domain are communicated via an
HTTP cookie, web browsers (and thus browser-based applications) will
automatically pass along such credentials when communicating with servers within
that domain. Furthermore, properly-equipped servers can cascade such credentials
to other servers further down the service chain by recognizing the
CW_CREDENTIALS cookie in the request and passing it along in the HTTP headers
of any requests that it makes.
A web service can determine the credentials of the current user in one of two
ways:
. by making a getCredentials request to a CubeWerx Authentication Server and parsing the unencrypted credentials that are returned the response.
. by decrypting the CW_CREDENTIALS cookie itself with the public key of a known (and trusted) CubeWerx Authentication Server.
A decrypted CW_CREDENTIALS cookie contains an XML representation of the user's
credentials, and has the following form:
xyzcorp.comJohnDoejdoe@xyzcorp.comjdoeUserAdministrator2012-08-21T05:06:52.158Zhttps://xyzcorp.com/cubewerx/cwauth.cgi
All child elements of other than and are
optional. There can be several elements. The element
indicates the URL of the CubeWerx Authentication Server that authenticated
the credentials.
=== Scenarios
==== Web-based application authenticating via Ajax request
. The user clicks a "log in" button on the web-based application.
. The web-based application prompts the user for a username and password.
. The web-based application makes an Ajax "login" request to the configured CubeWerx Authentication Server, passing along the user's username and password.
. The CubeWerx Authentication Server authenticates the user for the current domain and prepares a set of credentials which it encrypts using a private key and packages into a CW_CREDENTIALS cookie. This CW_CREDENTIALS cookie is then returned to the web-based application via the HTTP response headers. The HTTP response body contains an unencrypted version of the credentials in JSON format.
. The web browser automatically absorbs the CW_CREDENTIALS cookie and will include it in all future HTTP requests to all servers in the domain that the credentials were authenticated for. The web-based application optionally parses the JSON response and greets the user.
==== Web-based application redirecting to authentication server
. The user clicks a "log in" button on the web-based application.
. The web-based application directs the web browser to the login page of the configured CubeWerx Authentication Server, including a callback URL (back to the appropriate state of the web-based application) as a parameter of the login page's URL.
. The CubeWerx Authentication Server prompts the user for a username and password.
. The CubeWerx Authentication Server authenticates the user for the current domain and prepares a set of credentials which it encrypts using a private key and packages into a CW_CREDENTIALS cookie.
. The CubeWerx Authentication Server sends a web page back to the user displaying the authenticated credentials. The HTTP response headers of this web page include the CW_CREDENTIALS cookie, which the web browser automatically absorbs.
. The CubeWerx Authentication Server directs the web browser back to the web-based application, which then greets the user.
==== Server cascading credentials to another server
. A server receives a request that includes a CW_CREDENTIALS cookie in its HTTP headers.
. The server optionally decrypts the CW_CREDENTIALS cookie with the public key of an authentication server. This step is only necessary if this server itself needs to control access based on user identity or if the authenticated user needs to be identified for some other reason (such as for logging or for a personalized greeting message).
. When making a cascaded request to another server, the server checks the domain of the other server. If it's in the same second-level domain, it prepares a "Cookie" HTTP header containing a copy of the CW_CREDENTIALS cookie, and passes that along with the cascaded request.
==== Desktop application authenticating via the HTTP Basic Authentication mechanism
NOTE: This requires an HttpBasic-to-CwAuth bridge to be set up.
. The desktop application attempts to connect to CubeSERV via an "htcubeserv" URL, and is challenged for an HTTP-Basic identity.
. The user supplies a username and password, and the desktop application attempts the connection to CubeSERV again.
. The Http Basic Authentication module protecting the CubeSERV is configured to authenticate using the same underlying MySQL/MariaDB database that the local CwAuth server uses, and thus the username and password is recognized.
. The CubeSERV recognizes that it is being called through an HttpBasic-to-CwAuth bridge, and sends a passwordless login request to the companion CwAuth server to obtain the CwAuth identity for that user. A configured shared secret is supplied along with the request so that the CwAuth server knows to allow this passwordless login request.
. For every future connection that the desktop application makes to the CubeSERV, a cached HTTP-Basic identity will be sent, and steps 3 and 4 will be repeated.
=== CubeWerx Authentication Server
==== Deployment and configuration
===== Deployment
The CubeWerx Authentication Server is typically deployed under the URL
"cubeWerxSuiteDeploymentUrl/cwauth.cgi" on one or more of the web servers
in a particular domain. More than one authentication server can exist in a
single domain, and they can be identical (i.e., use the same backend
authentication database) or specialized. It is strongly recommended that all
authentication servers be accessible only through HTTPS in order to avoid the
possibility of authenticated credentials being sniffed in transit by a malicious
third party.
===== Preparation of keyrings
Since the CubeWerx Authentication Server relies on PGP public-key encryption, a
public/private key pair must be prepared for each deployed authentication server,
and the public keys of each of the deployed authentication server must be
distributed to the other CubeWerx Suite deployments in the domain. To do this,
for each CubeWerxSuite installation that provides an authentication server, do
the following:
----
cwauthadmin genKeyPair
----
This will generate a public/private key pair for the authenticatioh server. It
will take a few seconds, and you may be prompted to perform some additional
activity on the machine to help it generate good random numbers.
Then, on each of the other CubeWerx Suite installations in the domain, do the following:
----
cwauthadmin installKey
----
Example:
----
cwauthadmin installKey https://auth.xyzcorp.com/cubewerx/cwauth.cgi
----
This will fetch the public key from the authentication server and install it so
that this machine will be able to recognize credentials that are generated by
the authentication server.
At any time, you can get a list of which keys are installed (and for the
authentication servers themselves, which public/private keypairs are generated)
by typing:
----
cwauthadmin listKeys
----
The only public keys in a CubeWerx Suite keyring should be those of the
authentication servers for that domain. The existence of a public key in
a CubeWerx Suite keyring indicates that the server that that key represents
is a trusted source of authenticated credentials.
===== Configuration parameters
Several configuration parameters (with names of the form cwauth.*) exist for
configuring a CubeWerx Authentication Server. See their descriptions in the
Configuration Editor for more information.
===== Management of users and roles
To list the users and/or roles of a CubeWerx Authentication Server, execute one
of the following commands (in a command line shell on the authentication server
itself):
----
cwauthadmin listUsers
cwauthadmin listUserDetails []
cwauthadmin listRoles
cwauthadmin listRoleDetails []
----
To add, edit or remove the users and/or roles, execute one of the following
commands (new in CubeWerx Suite 7.2):
----
cwauthadmin addUser username=
email=
password=
[realName= []]
[firstName=]
[lastName=]
[roles=,,...]
----
----
cwauthadmin editUser username=
[email=]
[password=]
[realName= []]
[firstName=]
[lastName=]
[roles=,,...]
[addRoles=,,...]
[removeRoles=,,...]
----
----
cwauthadmin removeUser
----
----
cwauthadmin addRole role=
[description=]
[contact=]
[users=,,...]
----
----
cwauthadmin editRole role=
[newRolename=]
[description=]
[contact=]
[users=,,...]
[addUsers=,,...]
[removeUsers=,,...]
----
----
cwauthadmin removeRole
----
Alternatively, management of users and roles can be performed through
OpenImageMap.
=== Operations
CubeWerx Authentication Server operations can be invoked either via HTTP GET
(supplying the parameters as part of the URL) or via HTTP POST (supplying the
parameters in the body of the request with an application/x-www-form-urlencoded
MIME type). The usage of HTTP POST is recommended for the "login" operation in
order to prevent plaintext usernames and passwords from being visible in the
URL. Responses that indicate a status in the response body will also report this
status via an X-CwAuth-Status MIME header (new in CubeWerx Suite 7.4). If a
request to a CubeWerx Authentication Server contains cross-origin resource
sharing (CORS) headers, then the origin of the request must be in the same
CwAuth domain as the CubeWerx Authentication Server.
==== *_Auto_*
===== parameters
(none)
===== usage
If the user has valid credentials, displays these credentials in an HTML page
and provides the user with the ability to log out. Otherwise, presents a simple
HTML login page.
==== Login (HTML page)
===== parameters
----
operation=login
[&username=]
[&callback=]
----
===== usage
Presents a simple HTML login page. When the user submits this page, the "login" operation (described next) is triggered.
If a username is provided, the username field is pre-filled-in with this value.
If a callbackUrl is provided, then once the user has logged in successfully, a
button is presented which allows the user to go to that URL, returning the user
to the web application that invoked the login page.
==== *_Login_*
===== parameters
----
operation=login
&username=
&password=
&format=XML|JSON|HTML
[&callback=]
----
==== usage
Authenticates the user for the current domain (i.e., the second-level domain
name of the URL that the CubeWerx Authentication Server was invoked with) and
logs him/her in by supplying the user agent (e.g., web browser) with a
CW_CREDENTIALS cookie for that domain.
==== returns
If authentication is successful, a CW_CREDENTIALS cookie is returned in the
response HTTP headers, and a "loginSuccessful" response in the requested format
is returned in the response body. The response body includes unencrypted
credentials.
XML:
----
loginSuccessfulxyzcorp.comJohnDoejdoe@xyzcorp.comjdoeUserAdministrator2012-08-21T05:06:52.158Zhttps://xyzcorp.com/cubewerx/cwauth.cgi
----
JSON:
----
{
"status": "loginSuccessful",
"credentials": {
"domain": "xyzcorp.com",
"firstName": "John",
"lastName": "Doe",
"eMailAddress": "jdoe@xyzcorp.com",
"username": "jdoe",
"roles": [ "User", "Administrator" ],
"expires": "2012-08-21T05:06:52.158Z",
"originServer": "https://xyzcorp.com/cubewerx/cwauth.cgi"
}
}
----
HTML (if a callbackUrl is provided):
----
An HTTP redirection to the specified callbackUrl.
----
HTML (if a callbackUrl is not provided):
----
An HTML document showing the user's new credentials.
----
If authentication is unsuccessful, a response that indicates a status of
"loginFailed" is returned. If unsuccessful login requests are occurring too
frequently for this user, the login request is rejected and a response that
indicates a status of "loginAttemptsTooFrequent" is returned. This protects
the CubeWerx Authentication Server against brute-force password-cracking
attempts.
==== *_Logout_*
===== parameters
----
operation=logout
&format=XML|JSON|HTML
[&callback=]
----
===== usage
Logs the user out of the current domain (i.e., the second-level domain name of
the URL that the CubeWerx Authentication Server was invoked with) by requesting
that the user agent (e.g., web browser) expire the CW_CREDENTIALS cookie for
that domain.
===== returns
An empty CW_CREDENTIALS cookie with a cookie expiry date in the past is returned
in the response HTTP headers, and a "logoutSuccessful" response in the requested
format is returned in the response body.
XML:
----
logoutSuccessful
----
JSON:
----
{ "status": "logoutSuccessful" }
----
HTML (if a callbackUrl is provided):
----
An HTTP redirection to the specified callbackUrl.
----
HTML (if a callbackUrl is not provided):
----
An HTML document indicating that the user has been logged out.
----
==== *_GetCredentials_*
===== parameters
----
operation=getCredentials
&format=XML|JSON|HTML
[&callback=]
----
===== usage
Returns the user's current credentials (i.e., the unencrypted contents of the
user's CW_CREDENTIALS cookie) for the current domain.
===== returns
Either a "credentialsOkay", a "noCredentials", a "credentialsExpired" or a
"credentialsInvalid" response in the requested format is returned in the
response body. If "credentialsOkay" or "credentialsExpired", the response body
includes unencrypted credentials. Note that a CW_CREDENTIALS cookie is not
returned in the response HTTP headers, as this would be redundant. The
"credentialsInvalid" response response is returned in situations where the
user has credentials but they are not recognized by this authentication server.
XML:
----
credentialsOkayxyzcorp.comJohnDoejdoe@xyzcorp.comjdoeUserAdministrator2012-08-21T05:06:52.158Zhttps://xyzcorp.com/cubewerx/cwauth.cgi
----
or
----
noCredentials
----
or
----
credentialsExpired
...
----
or
----
credentialsInvalid
----
JSON:
----
{
"status": "credentialsOkay",
"credentials": {
"domain": "xyzcorp.com",
"firstName": "John",
"lastName": "Doe",
"eMailAddress": "jdoe@xyzcorp.com",
"username": "jdoe",
"roles": [ "User", "Administrator" ],
"expires": "2012-08-21T05:06:52.158Z",
"originServer": "https://xyzcorp.com/cubewerx/cwauth.cgi"
}
}
----
or
----
{ "status": "noCredentials" }
----
or
----
{
"status": "credentialsExpired",
"credentials": {
...
}
}
----
or
----
{ "status": "credentialsInvalid" }
----
HTML:
----
An HTML document showing the user's current credentials.
----
If a callbackUrl is provided, then the HTML response document will include a button which allows the user to go to that URL, returning the user to the web application that invoked the getCredentials operation.
==== *_RefreshCredentials_*
===== parameters
----
operation=refreshCredentials
&format=XML|JSON|HTML
[&callback=]
----
===== usage
Refreshes the user's current credentials by updating the expiry date and
supplying the user agent (e.g., web browser) with an updated CW_CREDENTIALS
cookie for that domain.
===== returns
Either a "credentialsRefreshed", a "noCredentials" a "credentialsExpired" or a
"credentialsInvalid" response in the requested format is returned in the
response body. If "credentialsRefreshed", a new CW_CREDENTIALS cookie is
returned in the response HTTP headers and the response body includes the
refreshed unencrypted credentials. If "credentialsExpired", the response
body includes the original (expired) unencrypted credentials.
XML:
----
credentialsRefreshedxyzcorp.comJohnDoejdoe@xyzcorp.comjdoeUserAdministrator2012-08-21T05:06:52.158Zhttps://xyzcorp.com/cubewerx/cwauth.cgi
----
or
----
noCredentials
----
or
----
credentialsExpired
...
----
JSON:
----
{
"status": "credentialsRefreshed",
"credentials": {
"domain": "xyzcorp.com",
"firstName": "John",
"lastName": "Doe",
"eMailAddress": "jdoe@xyzcorp.com",
"username": "jdoe",
"roles": [ "User", "Administrator" ],
"expires": "2012-08-21T05:06:52.158Z",
"originServer": "https://xyzcorp.com/cubewerx/cwauth.cgi"
}
}
----
or
----
{ "status": "noCredentials" }
----
or
----
{
"status": "credentialsExpired",
"credentials": {
...
}
}
----
HTML:
----
An HTML document showing the user's refreshed credentials.
----
If a callbackUrl is provided, then the HTML response document will include a button which allows the user to go to that URL, returning the user to the web application that invoked the refreshCredentials operation.
==== *_EditUserInfo (HTML page)_*
===== parameters
----
operation=editUserInfo
[&callback=]
----
===== usage
Presents a simple HTML page allowing the user to change his/her e-mail address,
name and/or password. When the user submits this page, the "editUserInfo"
operation (described next) is triggered.
If a callbackUrl is provided, then once the user has successfully changed
his/her information, a button is presented which allows the user to go to
that URL, returning the user to the web application that invoked the
editUserInfo page.
==== *_EditUserInfo_*
===== parameters
----
operation=editUserInfo
[&email=]
[&firstName=]
[&lastName=]
[&oldPassword=&newPassword=]
[&format=]
[&callback=]
----
===== usage
Changes the e-mail address, name and/or password in the CubeWerx Authentication
Server database record of the current user. If an attempt is made to change the
password, the user's current password must also be supplied.
===== returns
If the operation is successful, an updated CW_CREDENTIALS cookie is returned in
the response HTTP headers, and an "editUserInfoSuccessful" response in the
requested format is returned in the response body.
XML:
----
editUserInfoSuccessfulxyzcorp.comJohnDoejdoe@xyzcorp.comjdoeUserAdministrator2012-08-21T05:06:52.158Zhttps://xyzcorp.com/cubewerx/cwauth.cgi
----
JSON:
----
{
"status": "editUserInfoSuccessful",
"credentials": {
"domain": "xyzcorp.com",
"firstName": "John",
"lastName": "Doe",
"eMailAddress": "jdoe@xyzcorp.com",
"username": "jdoe",
"roles": [ "User", "Administrator" ],
"expires": "2012-08-21T05:06:52.158Z",
"originServer": "https://xyzcorp.com/cubewerx/cwauth.cgi"
}
}
----
HTML:
----
An HTML document indicating that the information has been successfully updated.
----
If a callbackUrl is provided, then the HTML response document will include a
button which allows the user to go to that URL, returning the user to the web
application that invoked the editUserInfo operation.
==== *_ForgotPassword_*
===== parameters
----
operation=forgotPassword
&username=
&format=XML|JSON|HTML
[&callback=]
----
===== usage
Indicates to the CubeWerx Authentication Server that the specified user has
forgotten his/her password. An e-mail message is sent to the e-mail address
registered for the user providing a URL that the user can click on to initiate
a password reset. This URL is a call to the "resetPassword" operation (with a
one-time authentication key), and is only valid for a limited time.
===== returns
A "passwordResetInitiated" response in the requested format is returned.
==== *_ResetPassword_*
===== parameters
----
operation=resetPassword
&username=
&authKey=
&format=XML|JSON|HTML
[&callback=]
----
===== usage
This is phase two of the "forgotPassword" operation, and is triggered via the
URL that is sent out as a result of that operation. If the specified authKey
matches the one that was set up by the "forgotPassword" operation, and it is
within the allowed time frame, the password of the specified user is reset to
a random value, and an e-mail message is sent to the user indicating what the
new password is.
===== returns
A "passwordResetComplete" response in the requested format is returned.
==== *_GetPublicKey_*
===== parameters
----
operation=getPublicKey
&format=XML|JSON|HTML
----
===== usage
Returns a PGP PUBLIC KEY BLOCK containing the public key of this CubeWerx
Authentication Server. It is this key that must be propagated to the other
servers in the domain so that they can verify the authenticity of credentials
that originate from this server.
===== returns
A PGP PUBLIC KEY BLOCK containing the public key of this CubeWerx Authentication
Server is returned (with a MIME type of application/pgp-keys). The format
parameter controls only the format of the returned exception report if an
internal error occurs.
==== *_Internal errors_*
For any operation, if an internal error occurs, an exception report in the
requested format is returned in the response body.
XML:
an OGC OWS 1.1 exception report with an HTTP response code of 500 ("Internal Server Error")
JSON:
----
{
"status": "exception",
"exception": [
{
"module": "CWAUTH",
"message": "",
"messageLang":"en",
"locationInfo": "