Estoy creando mi primera aplicación móvil usando Cordova. Los servicios de back-end se encuentran en Azure, por lo que estoy tratando de que la autenticación funcione mediante el complemento ADAL para Cordova.

En primer lugar, descubrí que la biblioteca no realiza intercepciones como lo hace la biblioteca ADAL para Angular. Estoy usando Angular dentro de mi aplicación Cordova, junto con las directivas de diseño de materiales para la apariencia. Hubiera sido bueno tener una interceptación, pero como entendí, simplemente no está allí en este momento (debería averiguar qué tan difícil es implementar).

Entonces, en cambio, ahora escribí un servicio que se encargará de enviar solicitudes de API REST a Azure, incluido el token de autenticación correcto. Se basa en la muestra que se encuentra aquí.

Esto es lo que se me ocurrió:

var request = function(url)
{
    createContext()
        .then(function () {
            getAuthToken().then(
                function(token) {
                    sendRequest(token, url);
            })
        },
        function (err) {
            $log.error("Failed to create a context.");
        });
};

Primero creará el contexto de autenticación:

function createContext () {
    return $q(function (resolve, reject) {
        var authenticationContext = Microsoft.ADAL.AuthenticationContext;

        authenticationContext.createAsync(authority)
            .then(function (context) {
                authContext = context;
                $log.log("Created authentication context for authority URL: " + context.authority);
                resolve();
            }, function (err) {
                $log.error("Failed to create authentication context: " + pre(err))
                reject();
            });
    });
};

El uso del contexto debería obtener el token de autenticación:

function getAuthToken()
{
    if (authContext == null) {
        $log.error('Authentication context isn\'t created yet. Create context first');
        return;
    }

    return $q(function (resolve, reject) {
        authContext.acquireTokenAsync(resourceUrl, appId, redirectUrl)
            .then(function (authResult) {
                resolve(authResult.accessToken);
            }, function (err) {
                $log.error("Failed to acquire token: " + pre(err));
                reject();
            });
    });
}

Y luego debería enviar la solicitud, pero dejaré esa parte ya que nunca llega allí de todos modos. Siento la necesidad de volver a enfatizar que soy un completo n00b en estas cosas, así que por favor sea fácil conmigo y especialmente con el código. Probablemente haya mucho margen de mejora, lo entiendo.

Cuando realmente ejecuto esto, aparece una ventana en la que necesito iniciar sesión con mi cuenta de Microsoft, genial. Incluso obtuve la autenticación de dos factores la primera vez que probé esto, ¡muy bien! Así que me conecto y vuelvo al código. Pero ahora la variable authresult tiene un estado de "Fallido" y no hay ningún token de acceso en el resultado. Desafortunadamente, tampoco hay indicios de qué salió mal. Entonces, la primera parte de la pregunta es; ¿Qué pudo haber salido mal aquí?

Ahora llegamos a la segunda parte de la pregunta; ¿Cómo se depura correctamente este tipo de cosas? En mi escritorio, ejecutaba Fiddler para verificar la comunicación, pero no sé cómo hacerlo para Android. Estoy depurando en mi dispositivo por cierto, porque por alguna razón todos los emuladores disponibles para mí son extremadamente lentos (VS y Google) a pesar de que mis especificaciones de hardware deberían ser compatibles con ellos.

Gracias por cualquier puntero!

Actualización 03-02-2016

Jugando un poco con el código, decidí empaquetar cosas en una función de inicio de sesión que da una muestra algo más corta:

var createContext = function () {
    if (authContext == null) {
        authContext = new Microsoft.ADAL.AuthenticationContext(authority);
    }
};

var getAuthToken = function () {
    if (authContext == null) {
        $log.error('Authentication context isn\'t created yet. Create context first');
        return;
    }

    return $q(function (resolve, reject) {
        authContext.acquireTokenAsync(endpointUrl, appId, redirectUrl)
            .then(function (authResult) {
                resolve(authResult.accessToken);
            }, function (err) {
                $log.error("Failed to acquire token: " + pre(err));
                reject();
            });
    });
}

var login = function () {
    createContext();
    getAuthToken();
}

Este código se ejecuta en las siguientes variables de entrada:

var authority = 'https://login.windows.net/[tenantid]';
var resourceUrl = 'https://graph.windows.net/';
var appId = '1ef41b17-0943-4359-bc12-014f4fd2d841';
var redirectUrl = 'http://MyApp';

Ahora usé chrome: // inspeccionar para ver qué pasa por el cable. Y para mi gran sorpresa, veo un token SAML válido devuelto desde Azure. Tiene mi nombre y todo, que reconocería que no enviarían después de una autenticación fallida. Entonces parece que aunque la respuesta es correcta, la biblioteca ADAL no me da una respuesta adecuada (Estado = Fallido). De nuevo, no tengo ni idea de cómo proceder: S

7
Jasper 29 ene. 2016 a las 10:02

2 respuestas

La mejor respuesta

Lo acabo de resolver. Y como era de esperar, el remedio es tan simple como parece. Configurando la aplicación en Azure AD, elegí la aplicación tipo "aplicación web", ya que esta es una aplicación web con Angular y todo. Ahora supongo que, dado que Cordova traduce las cosas al código nativo, esa no es la opción correcta para elegir. Tan pronto como creé una nueva aplicación como "aplicación nativa" en su lugar y usé el ID de cliente de esa, todo comenzó a funcionar ... ¡Sinceramente espero que esto ayude a alguien más en el futuro ...!

5
Jasper 9 feb. 2016 a las 13:26

Tuve un problema muy similar en el que intentaba acceder a una API web desde una aplicación de Cordova. Estaba usando el ID de la aplicación Uri para la API web a la que quería acceder como resouceURL al llamar a adquirirTokenAsync. Cuando cambié esto a la identificación del cliente de Web Api, funcionó.

0
JOC 1 feb. 2016 a las 12:42