Saltar al contenido principal
pdf?stylesheet=default
Blackboard Help

ID de acceso

La extensión de autenticación de ID de acceso se usa para realizar el inicio de sesión único (SSO) de un usuario en Joule desde un sistema externo, como CampusVue. La extensión de ID de acceso funciona mediante un secreto compartido entre Joule y el sistema externo. En función de este secreto compartido y un inicio de sesión administrativo configurado, el sistema externo genera una ficha de un solo uso que puede usarse para elaborar una URL única. El sistema externo proporciona la URL única al usuario y, una vez que este hace clic en ella, Joule valida el acceso del usuario según la IP del sistema externo, la ficha única y el secreto compartido. Este sistema es una autenticación basada en una ficha segura mediante un sistema compartido para construir y deconstruir fichas.

Ajustes globales del ID de acceso

  1. Para acceder a los ajustes del ID de acceso, navegue hasta el bloque Administración y seleccione Administración del sitio > Extensiones > Autenticación > Autenticación de ID de acceso.
  2. Configure los ajustes generales.
    • Lista de IP permitidas: ingrese todas las IP que pueden comunicarse con la extensión de autenticación. Coloque cada entrada en una línea. Solo las direcciones IP completas o las direcciones en notación CDIR serán aceptadas como entradas válidas.
    • Clave secreta: la clave secreta ingresada debe ser idéntica a la configurada del lado del sistema con la que está configurando el inicio de sesión único.
    • Nombre de usuario: especifique el nombre de usuario para acceder a la URL de extremo.
    • Contraseña: especifique la contraseña para acceder a la URL de extremo.
    • Búsqueda de usuarios: especifique el campo de perfil de usuario de Joule para las búsquedas de usuarios.
      • idnumber
      • username
    • Duración de ID de acceso: especifique la duración durante la cual es válido el ID de acceso generado (en minutos). Predeterminado: 5 minutos.
    • Algoritmo hash: especifique la validación del algoritmo hash para los parámetros de entrada.
      • SHA-256 (por defecto)
      • SHA-1

    Bloquear campos de usuario

    La sección Bloquear campos de usuario del ajuste de la extensión de autenticación se usa para bloquear el acceso de un usuario para actualizar un valor de un campo de perfil de usuario. Esto es útil para los datos de usuario que se actualizan mediante un sistema externo o que el administrador no desea que el usuario cambie una vez ingresados. Si bloquea campos requeridos por Moodle, asegúrese de proporcionar dichos datos al crear cuentas de usuario o las cuentas no podrán usarse. Considere establecer el modo de bloqueo en “Desbloqueado si está vacío” para evitar este problema. Los administradores solo pueden bloquear el siguiente campo de perfil:

    • Nombre
    • Apellido
    • Dirección de correo electrónico
    • Ciudad/pueblo
    • País
    • Idioma
    • Descripción
    • página web
    • Número de ID
    • Institución
    • Departamento
    • Teléfono 1
    • Teléfono 2
    • Dirección

    Cada campo de perfil puede configurarse en uno de los siguientes ajustes con el valor predeterminado desbloqueado:

    • Desbloqueado: el usuario puede cambiar el valor en el campo de perfil en cualquier momento.
    • Desbloqueado si está vacío: el usuario solo puede establecer el valor para el campo de perfil de usuario una vez. Si el valor es establecido por un sistema externo, el usuario no puede cambiarlo en Joule.
    • Bloquear: El usuario no puede cambiar el valor del campo de perfil de usuario en Joule; deben cambiarlo un administrador o un sistema externo.

    Ejemplo de flujo de trabajo de ID de acceso

    Ejemplo de flujo de trabajo de inicio de sesión único

    El siguiente es un ejemplo de flujo de trabajo para la configuración de un inicio de sesión único con autenticación de ID de acceso.

    Paso 1: generar la ficha

    El primer paso del inicio de sesión único con autenticación de ID de acceso requiere la generación de una ficha mediante un secreto precompartido. Consulte la autenticación de ID de acceso antes mencionada para ver un código de muestra de generación de ficha.

    Paso 2: validar la ficha

    El servidor cliente envía una solicitud al extremo del servicio web para generar la ficha, ubicado en https://site.url/auth/accessid/webservices.php. Reemplace "site.url" por el nombre del dominio de su sitio de Joule. La solicitud debe ser una PUBLICACIÓN a través de canales seguros (HTTPS). Además, la solicitud del servidor cliente debe validarse dentro del rango establecido mediante los ajustes de autenticación de ID de acceso Lista de IP permitidas. El "accessid" que se obtiene es válido durante el tiempo especificado en Duración de ID de acceso.

    La siguiente información debe aprobarse con cada publicación para la generación de la ficha:

    • username: el nombre de usuario preestablecido. Se configura en los ajustes de autenticación de ID de acceso dentro de Joule.
    • pass: la contraseña preestablecida. Se configura en los ajustes de autenticación de ID de acceso dentro de Joule.
    • timestamp: la misma marca de tiempo que se usó para generar la ficha.
    • token: la ficha, generada en el paso 1.
    • userid: el ID de usuario, según se define en el campo Búsqueda de usuarios en los ajustes de autenticación de ID de acceso dentro de Joule. Por ejemplo, si el ajuste Búsqueda de usuarios se configura en "idnumber", el número de ID se aprobaría en este campo.

    Respuesta correcta de ejemplo

    ​<?xml version="1.0" encoding="UTF-8"?>
    <?xml version="1.0" encoding="UTF-8"?>
    <auth_accessid_lib_server_service generator="zend" version="1.0">
      <get_accessid>
        <response>
          <accessid>hojHWTuH8oClZjfR</accessid>
        </response>
        <status>success</status>
      </get_accessid>
    </auth_accessid_lib_server_service>
    

    Respuesta incorrecta de ejemplo

    <?xml version="1.0" encoding="UTF-8"?>
    <rest generator="zend" version="1.0">
        <response>
            <message>Remote IP address of 111.111.111.111 failed to validate. If remote IP address is correct, then validate the Allowed IP list setting.</message>
        </response>
        <status>failed</status>
    </rest>
    

    Paso 3: redireccionar el usuario a Joule

    Una vez obtenido el accessid, el usuario debe ser redirigido al extremo en Joule para iniciar automáticamente la sesión de usuario en Joule: https://site.url/auth/accessid/acces...?id=[ACCESSID]

    Opcionalmente, el usuario puede ser redirigido a una página dentro de Joule. Esto es común cuando el usuario debe ser redirigido a un curso específico, en lugar de ser redirigido a la página principal o a Mi Moodle. En este caso, se aprobaría un parámetro "redirect" con codificación URL: https://site.url/auth/accessid/acces...ct=[LOCAL_URL]

    Para el redireccionamiento del curso, los parámetros podrían ser los siguientes:

    • %2Fcourse%2Fview.php%3Fid%3DXXX
    • %2Fcourse%2Fview.php%3Fname%3DXXX
    • %2Fcourse%2Fview.php%3Fidnumber%3DXXX

    Donde XXX es el valor con codificación URL de la ID interna, del nombre corto o de idnumber del curso, respectivamente. El usuario puede ser redirigido a cualquier parte dentro de Joule.

    Diagrama de ejemplo

    Ejemplos de código de ID de acceso

    Los siguientes ejemplos de códigos comparan un hash generado usando las variables:

    • Secreto compartido: GerwtYxxd34
    • userid: janedoe
    • timestamp: 1326827023
    • username: jdoe
    • pass: pass

    Ficha esperada: 153283f1909be96a23a3324b345098010320b0db1fd71a726bbad0ca3cfd67ff

    Ejemplo de Java 1

    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    /**
    * @author Darko Miletic
    *
    */
    public class Sample {
    
        public static String generate_token_impl(String[] params, String secret, String algorithm) {
            MessageDigest algo = null;
            try {
                algo = MessageDigest.getInstance(algorithm);
                StringBuilder sb = new StringBuilder();
                for (String param : params) {
                    String salted_param = secret + param;
                    sb.append(salted_param);
                }
                return byte2hex(algo.digest(sb.toString().getBytes()));
            } catch (NoSuchAlgorithmException excp) {
                return "";
            }
        }
    
        public static String generate_token(String[] params, String secret) {
            return generate_token_impl(params, secret, "SHA-256");
        }
    
        public static String byte2hex(byte[] hash) {
            StringBuilder sb = new StringBuilder();
            for (byte b : hash) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        }
        /**
         * @param args
         */
        public static void main(String[] args) {
            String[] testparams = {"janedoe", "1326827023", "jdoe", "pass"};
            String secret = "GerwtYxxd34";
            String known_result = "153283f1909be96a23a3324b345098010320b0db1fd71a726bbad0ca3cfd67ff";
            String result = generate_token(testparams, secret);
            if (result.equals(known_result)) {
                System.out.println("Hashes match");
            } else {
                System.out.println("Hashes DO NOT match:");
                System.out.println(result);
            }
        }
    
    }
    

    Ejemplo de Java 2

    import java.io.BufferedReader;
    import java.io.DataOutputStream;
    import java.io.InputStreamReader;
    import java.io.StringReader;
    import java.net.URL;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    import javax.net.ssl.HttpsURLConnection;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    
    import org.w3c.dom.CharacterData;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.InputSource;
    
    
    public class AccessIDGenerator {
    
    private final static String USER_AGENT = "Mozilla/5.0";
    private final static String FORWARD_URL =  "https://cccccccc-sandbox.mrooms.net/auth/accessid/access.php?id=";
    public static String generate_token_impl(String[] params, String secret, String algorithm) {
    MessageDigest algo = null;
    try {
    algo = MessageDigest.getInstance(algorithm);
    StringBuilder sb = new StringBuilder();
    for (String param : params) {
    String salted_param = secret + param;
    sb.append(salted_param);
    }
    return byte2hex(algo.digest(sb.toString().getBytes()));
    } catch (NoSuchAlgorithmException excp) {
    return "";
    }
    }
    
    public static String generate_token(String[] params, String secret) {
    return generate_token_impl(params, secret, "SHA-256");
    }
    
    public static String byte2hex(byte[] hash) {
    StringBuilder sb = new StringBuilder();
    for (byte b : hash) {
    sb.append(String.format("%02x", b));
    }
    return sb.toString();
    }
    
    public static String getAccessID(String token) {
    
    try {
    String url = "https://cccccccc-sandbox.mrooms.net/auth/accessid/webservices.php"; URL obj = new URL(url);
    HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
    
    //add request header
    con.setRequestMethod("POST");
    con.setRequestProperty("User-Agent", USER_AGENT);
    con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
    
    String urlParameters = "username=" + username + "&pass=" + pass + "&timestamp=" + timestamp + "&token=" + token + "&userid=" + userid;
    
    // Send post request
    con.setDoOutput(true);
    DataOutputStream wr = new DataOutputStream(con.getOutputStream());
    wr.writeBytes(urlParameters);
    wr.flush();
    wr.close();
    
    int responseCode = con.getResponseCode();
    System.out.println("\nSending 'POST' request to URL : " + url);
    System.out.println("Post parameters : " + urlParameters);
    System.out.println("Response Code : " + responseCode);
    
    BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();
    
    while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
    }
    in.close();
    
    //print result
    //System.out.println(response.toString());
    return response.toString();
    } catch (Exception l_ex) {
    
    }
    return "";
    
    }
    
    static String parseAccessId (String xmlString) {
    try {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    
    // Load the input XML document, parse it and return an instance of the
    // Document class.
    InputSource is = new InputSource();
    is.setCharacterStream(new StringReader(xmlString));
    
    Document document = builder.parse(is);
    
    NodeList nodeList = document.getDocumentElement().getChildNodes();
    for (int i = 0; i < nodeList.getLength(); i++) {
    Node node = nodeList.item(i);
    
    if (node.getNodeType() == Node.ELEMENT_NODE) {
    Element element = (Element) node;
    System.out.println(element.getNodeName());
    NodeList name = element.getElementsByTagName("accessid");
    Element line = (Element) name.item(0);
    return getCharacterDataFromElement(line);
    
    }
    }
    } catch (Exception l_ex) {
    l_ex.printStackTrace();
    }
    return "";
    }
    
    public static String getCharacterDataFromElement(Element e) {
    Node child = e.getFirstChild();
    if (child instanceof CharacterData) {
    CharacterData cd = (CharacterData) child;
    return cd.getData();
    }
    return "";
    }
    /**
    * @param args
    */
    public static void main(String[] args) {
    timestamp = Long.toString((long)System.currentTimeMillis()/1000);
    System.out.println("Timestamp; " + timestamp);
    String[] testparams = {userid, timestamp,username, pass};
    String secret = "GerwtYxxd34";
    String known_result = "153283f1909be96a23a3324b345098010320b0db1fd71a726bbad0ca3cfd67ff";
    String result = generate_token(testparams, secret);
    System.out.println("Token is: " + result);
    /*
    if (result.equals(known_result)) {
    System.out.println("Hashes match");
    } else {
    System.out.println("Hashes DO NOT match:");
    System.out.println(result);
    }
    */
    
    String response = getAccessID(result);
    System.out.println("Parsing the XML String: "+ response);
    
    String accessId = parseAccessId(response);
    System.out.println("Access ID: " + accessId);
    System.out.println ("URL: " + FORWARD_URL + accessId);
    
    }
    
    private static String username = "joe.NAME";
    private static String pass = "gaaaps22GPS@";
    private static String userid = "joe.instructor";
    private static String timestamp = null;
    }
    

    Ejemplo de PHP

    /**
    * @param array $params
    * @param string $secret
    * @return string
    */
    function generate_token(array $params, $secret) {
        $hashstorage = '';
        foreach ($params as $param) {
            $hashstorage .=  $secret.$param;
        }
        $result = hash('SHA256', $hashstorage);
        return $result;
    }
    
    $secret = 'GerwtYxxd34';
    $testparams = array(
        'userid'    => 'janedoe',
        'timestamp' => '1326827023',
        'username'  => 'jdoe',
        'pass'      => 'pass'
    );
    $known_result = '153283f1909be96a23a3324b345098010320b0db1fd71a726bbad0ca3cfd67ff';
    $result = generate_token($testparams, $secret);
    if ($result === $known_result) {
        echo 'Hashes match!'.PHP_EOL;
    } else {
        echo 'Hashes DO NOT match!'.PHP_EOL;
    }