router-authz.js revision 0589fafd98a08996e07c547cf9af82808c323135
039cd2c4871a00e51af909222a34695d9cec3000vboxsync/*! @license
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
039cd2c4871a00e51af909222a34695d9cec3000vboxsync *
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * Copyright © 2011-2012 ForgeRock AS. All rights reserved.
039cd2c4871a00e51af909222a34695d9cec3000vboxsync *
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * The contents of this file are subject to the terms
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * of the Common Development and Distribution License
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (the License). You may not use this file except in
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * compliance with the License.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You can obtain a copy of the License at
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * http://forgerock.org/license/CDDLv1.0.html
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * See the License for the specific language governing
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * permission and limitations under the License.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * When distributing Covered Code, include this CDDL
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * Header Notice in each file and include the License file
12cd783de945853c8fc377095e8d0bbd4c97d8a1vboxsync * at http://forgerock.org/license/CDDLv1.0.html
27537ffef7291d0bb3a24e459a6b94c65586defevboxsync * If applicable, add the following below the CDDL Header,
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * with the fields enclosed by brackets [] replaced by
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * your own identifying information:
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * "Portions Copyrighted [year] [name of copyright owner]"
039cd2c4871a00e51af909222a34695d9cec3000vboxsync */
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
039cd2c4871a00e51af909222a34695d9cec3000vboxsync/*
3f8fa562bb916e87b0beff9ec2a4e241c643dcc8vboxsync * This script is called from the router "onRequest" trigger, to enforce a central
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * set of authorization rules.
039cd2c4871a00e51af909222a34695d9cec3000vboxsync *
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * This default implemention simply restricts requests via HTTP to users that are assigned
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * an "openidm-admin" role, and optionally to those that authenticate with TLS mutual
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * authentication (assigned an "openidm-cert" role).
039cd2c4871a00e51af909222a34695d9cec3000vboxsync */
af5fce523ceaf4ada0d4d919d9783c749ad72bc9vboxsync
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync// If true, then allows HTTP requests from "openidm-cert" role.
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsyncconst allowCert = false;
af1bd0025dd5d8be5f1468689d0d77d4839a3be5vboxsync
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsyncfunction contains(a, o) {
1032ee3ece58eb60a4d3fb08ff5be8b848eb98bbvboxsync if (typeof(a) != 'undefined' && a != null) {
ab9c7333d588df5d6959a3b2c96c60321d26c4b0vboxsync for (var i = 0; i <= a.length; i++) {
ab9c7333d588df5d6959a3b2c96c60321d26c4b0vboxsync if (a[i] === o) {
af1bd0025dd5d8be5f1468689d0d77d4839a3be5vboxsync return true;
b26977a29bd8af11e3059ef8fb47a92a1241f20dvboxsync }
64a48ec134be9af6c232948fb8906edc6f385f61vboxsync }
ab9c7333d588df5d6959a3b2c96c60321d26c4b0vboxsync }
ab9c7333d588df5d6959a3b2c96c60321d26c4b0vboxsync return false;
3f279f58d7fa1cfb1ef999f80968cf3aefc0680cvboxsync}
ab9c7333d588df5d6959a3b2c96c60321d26c4b0vboxsync
9e57274211125689926b35d1916c0c5c82b33670vboxsync/**
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * Public methods are accessible by anonymous user. They are used
039cd2c4871a00e51af909222a34695d9cec3000vboxsync * during registration and forgotten password process.
039cd2c4871a00e51af909222a34695d9cec3000vboxsync */
039cd2c4871a00e51af909222a34695d9cec3000vboxsyncfunction isPublicMethodInvocation() {
039cd2c4871a00e51af909222a34695d9cec3000vboxsync logger.debug("request.parent.path = {}", request.parent.path);
e001cafceea8efd540f21109f6ab293f744ebb0bvboxsync logger.debug("request.parent.method = {}", request.parent.method);
ab9c7333d588df5d6959a3b2c96c60321d26c4b0vboxsync
ab9c7333d588df5d6959a3b2c96c60321d26c4b0vboxsync if (request.parent.path.match('^/openidm/managed/user') == '/openidm/managed/user') {
53ed059bdb30c2b20a3f329602bb715d75ab7d56vboxsync logger.debug("Resource == user");
ab9c7333d588df5d6959a3b2c96c60321d26c4b0vboxsync
53ed059bdb30c2b20a3f329602bb715d75ab7d56vboxsync if (request.parent.method == 'GET') {
53ed059bdb30c2b20a3f329602bb715d75ab7d56vboxsync logger.debug("This is GET request. Selected allowed only. Checking queries.");
ab9c7333d588df5d6959a3b2c96c60321d26c4b0vboxsync
9e57274211125689926b35d1916c0c5c82b33670vboxsync var publicQueries = ['check-userName-availability','for-security-answer','for-credentials', 'get-security-question', 'set-newPassword-for-userName-and-security-answer'];
039cd2c4871a00e51af909222a34695d9cec3000vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (request.params) {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync var queryName = request.params['_query-id'];
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync }
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync if (queryName && (publicQueries.indexOf(queryName) > -1)) {
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync logger.debug("Query {} found in the list", queryName);
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync return true;
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync } else {
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync logger.debug("Query {} hasn't been found in a query", queryName);
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync return false;
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync }
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync } else if (request.parent.method == 'POST') {
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync logger.debug("PUT request detected");
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync return true;
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync } else {
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync logger.debug("Anonymous POST and DELETE methods are not allowed");
039cd2c4871a00e51af909222a34695d9cec3000vboxsync }
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync } else {
8a0ee4ffcd453884e357b4d5984ae3b7146abb6fvboxsync logger.debug("Anonymous access not allowed for resources other than user");
8a0ee4ffcd453884e357b4d5984ae3b7146abb6fvboxsync return false;
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync }
c4fd771ce163c73d7ac90e267e84de29314f5e97vboxsync}
8a0ee4ffcd453884e357b4d5984ae3b7146abb6fvboxsync
8a0ee4ffcd453884e357b4d5984ae3b7146abb6fvboxsyncfunction userIsAuthorized(roles) {
return contains(roles, 'openidm-authorized');
}
function requestIsAQueryOfName(queryName) {
return request.params && request.params['_query-id'] && request.params['_query-id'] == queryName;
}
function authorizedUsernameEquals(userName) {
return request.parent.security['user'] == userName;
}
function requestIsAnActionOfName(actionName) {
return request.value && request.params && request.params['_action'] && request.params['_action'] == actionName;
}
function requestValueContainsReplaceValueWithKeyOfName(valueKeyName) {
var key = "replace";
for (var i = 0; i < request.value.length; i++) {
if (request.value[i][key] == valueKeyName) {
return true;
}
}
}
function allow() {
if (typeof(request.parent) === 'undefined' || request.parent.type != 'http') {
return true;
}
var roles = request.parent.security['openidm-roles'];
if (contains(roles, 'openidm-admin') || contains(roles, 'admin')) {
//administrator can do everything
return true;
} else if (allowCert && contains(roles, 'openidm-cert')) {
//certificated user can do everything
return true;
} else if (requestIsAQueryOfName('for-userName') && userIsAuthorized(roles)){
//authenticated user can only manage his data and cannot change a role attribute.
var requestedUserNameDataIdentificator = request.params['uid'];
if (authorizedUsernameEquals(requestedUserNameDataIdentificator)) {
logger.debug("User manipulation with own data");
if (requestIsAnActionOfName('patch')) {
logger.debug("Request is a patch. Checking if trying to change own role");
if (requestValueContainsReplaceValueWithKeyOfName('/role')) {
logger.debug("Trying to change own role is forbidden for standard user");
return false;
}
}
} else {
logger.debug("Manipulation with data of user not equal to logged-in is forbidden");
throw "Access denied (Manipulation with data of user not equal to logged-in is forbidden)";
}
return true;
} else {
return isPublicMethodInvocation();
}
}
if (!allow()) {
throw "Access denied";
}