Autenticación app-only para usar la API Microsoft Graph en webjobs de Azure

Muy buenas a todos

En entradas anteriores, hemos visto cómo empezar a trabajar con el servicio de búsqueda de Azure, creando los índices. Dentro de mi objetivo a la hora de trabajar con este servicio, estaba el de indexar contenido de Office 365 usando la API Microsoft Graph por medio de webjobs. Y es aquí donde entra lo que os quiero contar hoy.

El flujo habitual de autenticación para usar la API Microsoft Graph en nuestras aplicaciones está basado en el protocolo OAuth2. Este protocolo parte de un token que hace una delegación de una serie de permisos específicos para un usuario concreto. Para obtener este token, es necesario que el usuario se identifique en Office 365 al menos una vez, por lo que tiene que introducir sus credenciales en una pantalla de autenticación que se muestra en pantalla.

Sin embargo, hay una serie de aplicaciones en las que este flujo de autenticación no es posible, aplicaciones que ejecutan tareas en background y en las que no hay un usuario como pueden ser los webjobs. Para este tipo de aplicaciones, el protocolo OAuth2 proporcionar un flujo adicional de autenticación y es el que vamos a usar para acceder a la API de Microsoft Graph en una aplicación que se va a ejecutar en un webjob de Azure. Podemos usar este flujo de autenticación, de momento, para obtener acceso a las API de contactos, mail y calendario. He estado probando y para OneDrive aún no está soportado.

Antes de nada, os voy a dejar los enlaces donde he encontrado toda la información y el tutorial para poder configurar la aplicación y todo lo que hay que hacer en Azure para que funcione correctamente.

http://www.eliostruyf.com/building-daemon-or-service-app-with-the-microsoft-graph-api/

http://blogs.msdn.com/b/exchangedev/archive/2015/01/21/building-demon-or-service-apps-with-office-365-mail-calendar-and-contacts-apis-oauth2-client-credential-flow.aspx

Creando los permisos para la aplicación en AAD

El primer paso que tenemos daremos será configurar los permisos de nuestra aplicación en Azure Active Directory.

1.- Accedemos a Azure, el portal clásico y vamos a la sección de Azure Active Directory. Una vez ahí nos vamos al apartado de aplicaciones, donde añadiremos una nueva aplicación.

Captura de pantalla 2016-01-24 a las 16.28.51

2.- Seleccionamos la opción de “Agregar una aplicación que mi organización está desarrollando” y de tipo “Aplicación Web y/o API Web” ya que la otra opción no soporta el tipo de autenticación app-only que vamos a configurar.

Captura de pantalla 2016-01-24 a las 16.29.04

Captura de pantalla 2016-01-24 a las 16.29.28

3.- Indicamos la URL de inicio de sesión y la URI de la aplicación. El primero de los dos valores, no es importante, en este caso hemos añadido la url donde el webjob estará alojado.

Captura de pantalla 2016-01-24 a las 16.30.49

4.- Vamos a la nueva aplicación que hemos añadido y en la pestaña “Configuración”, vamos a la parte final, de permisos, ahí añadimos permisos para Microsoft Graph.

Captura de pantalla 2016-01-24 a las 16.31.30

Captura de pantalla 2016-01-24 a las 16.31.42

5.- Una vez añadidos, tenemos que indicar en el desplegable de “Permisos de la Aplicación” (ya que los permisos los vamos a conceder directamente a la aplicación), los servicios para los que tendrá permisos.

Captura de pantalla 2016-01-24 a las 16.31.57

6.- Una vez terminado pulsamos Guardar.

Creando y configurando los certificados

A continuación necesitamos generar los certificados y configurarlos en nuestra aplicación web (que también tendremos que crear) y en la aplicación que acabamos de crear en nuestro AAD.

1.- En primer lugar, abrimos la consola de comandos y creamos el certificado, sustituyendo Tenant y AppName por los valores que correspondan

makecert -r -pe -n “CN=Tenant AppName Cert” -b 11/25/2015 -e 11/25/2017 -ss my -len 2048

2.- A continuación, vamos a exportar dicho certificado como PFX y CER. Para ello primero abrimos el Microsoft Management Console (mmc.exe).

3.- Una vez aquí, vamos a archivo->Agregar o quitar complemento y ahí añadimos la opción certificados.

cer1

4.- A continuación, buscamos el certificado que acabamos de crear y hacemos click sobre el botón derecho del mismo y seleccionamos Todas las tareas->exportar

cer3

Tenemos dos opciones de exportación, “Exportar la clave privada” y “No exportar la clave privada”, ejecutaremos la exportación dos veces y completaremos el asistente para cada una de éstas opciones, generando los dos certificados.

5.- Ahora, volvemos nuevamente a la aplicación que hemos creado en Azure Active Directory para configurar el certificado en la misma. Esto no se puede hacer a través de una interfaz gráfica, por lo que habrá que hacerlo modificando el manifest. Para ello, lo primero que debemos hacer es recuperar las claves del certificado CER que hemos obtenido, esto lo podemos hacer por medio del siguiente script de powershell:


$certPath = Read-Host "Enter certificate path (.cer)"
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($certPath)
$rawCert = $cert.GetRawCertData()
$base64Cert = [System.Convert]::ToBase64String($rawCert)
$rawCertHash = $cert.GetCertHash()
$base64CertHash = [System.Convert]::ToBase64String($rawCertHash)
$KeyId = [System.Guid]::NewGuid().ToString()
Write-Host "base64Cert:" $base64Cert
Write-Host "base64CertHash:" $base64CertHash
Write-Host "KeyId:" $KeyId

Este script nos devuelve las tres claves que nos hacen falta.

6.- Ahora, descargamos el manifest de la aplicación:

Captura de pantalla 2016-01-24 a las 17.46.09

Captura de pantalla 2016-01-24 a las 17.46.25

7.- Y sustituimos la siguiente cadena:


"keyCredentials": []

por


"keyCredentials": [
 {
 "customKeyIdentifier": "base64CertHash",
 "keyId": "KeyId",
 "type": "AsymmetricX509Cert",
 "usage": "Verify",
 "value": "base64Cert"
 }
],

Sustituyendo los valores “base64CertHash”, “KeyId” y “base64Cert”, por la cadena correspondiente obtenida de la ejecución del script powershell anterior.

8.- Ahora tenemos que volver a cargar el manifest modificado en la aplicación con lo que habremos terminado de configurar los permisos de nuestra app en Azure Active Directory.

9.- A continuación, creamos una aplicación web de Azure y cargamos el certificado PFX en la misma.

Captura de pantalla 2016-01-24 a las 17.57.36

Es necesario escalar la aplicación web a nivel básico

Captura de pantalla 2016-01-24 a las 17.58.28

En la pestaña configuración de la aplicación web, hacemos click en Cargar un certificado

Captura de pantalla 2016-01-24 a las 17.59.15

Captura de pantalla 2016-01-24 a las 18.01.35

En la sección de configuración de aplicación, añadimos el valor WEBSITE_LOAD_CERTIFICATES con la huella digital que hemos obtenido al cargar el certificado.

Captura de pantalla 2016-01-24 a las 18.07.42

Y por fin, habremos configurado los certificados en Azure. Ahora no solo nos queda publicar y probar el WebJobs.

Creando y publicando el webjob en Azure 

Vamos a crear una nueva aplicación de consola con el código del WebJob que vamos a publicar.

Para esta aplicación hay que añadir las siguientes referencias:

  • System.Configuration

Y Añadir a través de Nuget la librería ADAL y RestSharp.

Además en el app.config, debemos añadir las siguientes propiedades:


 <appSettings>;
 <add key="GraphUrl" value="https://graph.microsoft.com"/>;
 <add key="ClientId" value="clientidaad"/>;
 <add key="Thumbprint" value="thumbprint"/>;
 <add key="Authority" value="https://login.windows.net/tenant.onmicrosoft.com/"/>;
 </appSettings>;

Debemos de sustituir el clientidaad por el ClientId de la aplicación que hemos creado en el Azure Active Directory, el valor de thumbprint por la huella obtenida al cargar el certificado en la aplicación web y por último sustituir el valor tenant por el nombre de nuestra organización.

Lo que nos queda ahora, es el código de la aplicación de consola de ejemplo, que es el siguiente:


class Program
 {
 private static readonly string GraphUrl = ConfigurationManager.AppSettings["GraphUrl"];
 private static readonly string ClientId = ConfigurationManager.AppSettings["ClientId"];
 private static readonly string Authority = ConfigurationManager.AppSettings["Authority"];
 private static readonly string Thumbprint = ConfigurationManager.AppSettings["Thumbprint"];

static void Main(string[] args)
 {
 //&nbsp;Recuperar el certificado
 var certificate = GetCertificate();

//&nbsp;Recuperar el token de acceso
 var token = GetAccessToken(certificate);

//&nbsp;Obtener los contactos
 var client = new RestClient(GraphUrl);
 var request = new RestRequest("/v1.0/users/&lt;userid&gt;/contacts", Method.GET);
 request.AddHeader("Authorization", "Bearer " + token.Result);
 request.AddHeader("Content-Type", "application/json");
 request.AddHeader("Accept", "application/json");

var response = client.Execute(request);
 var content = response.Content;

Console.WriteLine(content);

}

private static X509Certificate2 GetCertificate()
 {
 X509Certificate2 certificate = null;
 var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
 certStore.Open(OpenFlags.ReadOnly);
 var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, Thumbprint, false);

 if (certCollection.Count &gt; 0)
 {
 certificate = certCollection[0];
 }
 certStore.Close();
 return certificate;
 }

private static async Task&lt;string&gt; GetAccessToken(X509Certificate2 certificate)
 {
 var authenticationContext = new AuthenticationContext(Authority, false);
 var cac = new ClientAssertionCertificate(ClientId, certificate);
 var authenticationResult = await authenticationContext.AcquireTokenAsync(GraphUrl, cac);
 return authenticationResult.AccessToken;
 }
 }

El último paso es publicar la aplicación como un WebJob de Azure. Para ello, haciendo click en botón derecho sobre el proyecto de consola, seleccionaremos la opción Publish as Azure WebJob

public1

A continuación, indicamos la planificación del WebJob:

public2

Seleccionamos la aplicación web a la que queremos asociar el WebJob:

public3

Por último publicamos el WebJob.

public4

Y esto es todo, podemos probarlo ejecutando una vez el WebJob en Azure y ver que al final, se devuelven los contactos del usuario que le hemos indicado.

Captura de pantalla 2016-01-24 a las 19.05.09

Hasta aquí el post de hoy. Con lo que hemos visto en este post, podemos consumir información de Office 365 desde aplicaciones en background que no nos permiten usar el flujo habitual de autenticación del protocolo OAuth2.

Espero que os haya resultado interesante, en futuros post usaremos todo lo que hemos visto hoy para indexar contenido de Office 365 en Azure Search a través de un WebJob como el que hemos creado hoy.

Hasta la próxima

 

 

La nueva API de Office 365 Unificada

Buenas tardes a todos,

Esta semana desde Microsoft se lanzó la noticia de la aparición de una nueva API de Office 365 unificada, que busca facilitar y estandarizar todas las operaciones que se pueden realizar contra los servicios de Office 365 a través de su API, además de añadir nuevas opciones y servicios a la misma. Ayer tuve la oportunidad de echar un vistazo a esta API unificada y me pareció que mejora mucho la versión anterior y particularmente me gusta más esta línea que la que llevaba hasta ahora.

Hoy os voy a contar en qué consisten todas estas mejoras y enseñaros un ejemplo de cómo trabajar con ella que podréis comparar con un ejemplo que publiqué hace un tiempo sobre el uso de la API de Office 365 que hasta ahora teníamos vigente. Esta versión de API unificada está aún en Preview, por lo que aún pueden haber mejoras o modificaciones, no obstante lo que veremos hoy es la filosofía de la misma.

Antes de entrar de lleno os voy a dejar una recopilación de enlaces que creo que son fundamentales para entender la nueva API Unificada.

http://dev.office.com/unifiedAPIs

https://msdn.microsoft.com/office/office365/HowTo/office-365-unified-api-overview#msg_how_learn_unified_api

https://msdn.microsoft.com/en-us/office/office365/howto/get-started-with-office-365-unified-api

https://msdn.microsoft.com/en-us/office/office365/howto/office-365-unified-api-reference

http://www.vrdmn.com/2015/05/using-office-365-unified-api-in-aspnet.html

¿En qué consiste esta API de Office 365 Unificada?

La nueva API de Office 365 Unificada pretende seguir ofreciendo a los desarrolladores la oportunidad de utilizar los servicios de la suite de productividad de Office 365, pero de forma unificada y a través de una API REST, que nos permite hacer todas las operaciones de una forma mucho más sencilla y alineada con el “standard” de las API de servicios web hoy en día.

Además añaden acceso a nuevos servicios dentro de Office 365, quedando ahora el mapa de entidades de la siguiente forma:

O365_unified_API_entities

Con la API tradicional para usar algunas de las entidades disponibles teníamos siempre que realizar las siguientes acciones:

  • Usar el servicio discovery para encontrar los endpoints
  • Determinar la URL de los servicios a los que la app se quería conectar
  • Obtener y manejar el token de cada servicio y hacer la petición a cada uno de ellos directamente

Desde ahora, por medio de esta nueva API unificada, evitaremos estas operaciones para sustituirlas por una simple API REST. Además no es necesario descubrir y navegar a cada uno de los diferentes endpoints para cada servicio ya que todos comparten uno mismo, con lo que comparten también el sistema de autenticación y autorización. Estos nos permite además fácilmente consumir desde cualquier herramienta o lenguaje de programación esta API.

¿Cómo podemos usar la API?

Vamos a ver ahora algunas de las URLs que tenemos disponible en la API REST unificada para acceder a las distintas entidades de Office 365.

La Url de referencia al servicio la tenemos en la siguiente dirección https://graph.microsoft.com/{version}. A partir de aquí, voy a dejar distintos ejemplo de cómo podemos usar esta referencia para acceder a las distintas entidades.

Acceder a One Drive
https://graph.microsoft.com/{version}/me/files
Accediendo al servicio de Exchange OnLine
https://graph.microsoft.com/{version}/me/Messages
Accediendo a los usuarios de mi tenant
https://graph.microsoft.com/{version}/{myOrganization}/users
Accediendo a los grupos de Office 365
https://graph.microsoft.com/{version}/{myOrganization}/groups
Aplicaciones registradas en Azure AD
https://graph.microsoft.com/{version}/{myOrganization}/applications

Obviamente estas son solo algunas de las URLs principales de los servicios. En el enlace a la referencia de la API podemos ver todas las opciones y todas las oportunidades que tenemos disponibles y os animo a que naveguéis por ahí para ver todo lo que se puede hacer, que como veréis es mucho.

Ejemplo de uso de la nueva API de Office 365 Unificada

Para terminar con el artículo, vamos a ver un ejemplo de código de cómo podemos usar en una aplicación MVC esta nueva API REST.

Para poder usar la API REST unificada de Office 365, tenemos en primer lugar que registrar nuestra App en Azure Active Directory tal y como se comentaba en la entrada que os enlazo a continuación:

Registrando una aplicación en Azure Active Directory

Lo único que tenemos que hacer diferente a cuando íbamos a usar la versión anterior es a la hora de establecer los permisos para la app que estamos registrando. En esta ocasión deberemos añadir los permisos para la nueva API unificada, como se ve en la imagen siguiente, tenemos esta opción disponible.

unifiedAPI

Una vez que ya hemos registrado adecuadamente nuestra app, podemos pasar al código de la aplicación. En la demo que vamos a ver, voy a leer los archivos y directorios de mi One Drive, tal y como hice en el ejemplo con la API anterior. He creado una aplicación MVC y todo el código por simplicidad en el ejemplo, lo he puesto en la misma acción del controlador, aunque si accedéis al último enlace de los que indiqué arriba, podréis ver como se podría organizar el código a través de varias acciones en una aplicación MVC. Vamos a ver el código y luego lo explicaré destacando los puntos más importantes del mismo:

public async Task<ActionResult> Files(string  code)
{
       string authCode = Request.Params["code"];

       // The url in our app that Azure should redirect to after successful signin
       string redirectUri = Url.Action("Files", "Home", null, Request.Url.Scheme);

       var authContext = new AuthenticationContext("https://login.microsoftonline.com/common");

       if(authCode == null)
       {

           // Generate the parameterized URL for Azure signin
           Uri authUri = authContext.GetAuthorizationRequestURL("https://graph.microsoft.com/", ConfigurationManager.AppSettings["ida:ClientID"],
               new Uri(redirectUri), UserIdentifier.AnyUser, null);

           // Redirect the browser to the Azure signin page
           return Redirect(authUri.ToString());
       }

       ClientCredential creds = new ClientCredential(
           ConfigurationManager.AppSettings["ida:ClientID"],
           ConfigurationManager.AppSettings["ida:Password"]);

       // Get the token
       var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
           authCode, new Uri(redirectUri), creds, "https://graph.microsoft.com/");

       // Save the token
       string accesstoken = authResult.AccessToken;

       // Make request
       using (var client = new HttpClient())
       {
           string endpointUri, resourceId;

           using (var request = new HttpRequestMessage(HttpMethod.Get,
             "https://graph.microsoft.com/beta/me/files"))
           {
               request.Headers.Add("Authorization", "Bearer " + accesstoken);

               using (var response = await client.SendAsync(request))
               {
                   List<OneDriveFile> modelList = new List<OneDriveFile>();

                   var content = await response.Content.ReadAsStringAsync();
                   foreach (var item in JObject.Parse(content)["value"])
                   {
                       OneDriveFile newFile = new OneDriveFile
                       {
                          Name = item["name"].ToString(),
                          Size = double.Parse(item["size"].ToString())
                       };

                       modelList.Add(newFile);
                   }

                   ViewBag.files = modelList;

                }
            }
       }

       return View();
}

Vamos a destacar tres aspectos fundamentales de este código:

  • Lo primero que haremos en nuestro código es comprobar si nos hemos autenticado contra Azure Directory, tal y como hacíamos con la API tradicional, y en el caso de que no lo esté nos redirigirá a la página correspondiente para autenticarnos, para todo el proceso de autenticación y autorización se va a usar como hacíamos anteriormente la librería ADAL que tenemos en Nuget. (Líneas 10 a 19)
  • El siguiente paso, es capturar el token de acceso para obtener autorización al hacer las peticiones REST. (Líneas 26 a 30)
  • En el último paso usaremos un cliente Http que nos proporciona C# para hacer llamadas a la API y procesar las respuestas. (Líneas 33 a 62)

Las diferencias con respecto al uso de la versión anterior de la API para Office 365 basada en el servicio discovery la podemos ver con la entrada que publiqué sobre este tema. Nos obstante son obvias, por la facilidad con la que ahora podemos acceder a la API de Office, sin tener que hacer todos los pasos para simplemente acceder al servicio que eran necesarios. Esta es la entrada que os comentaba.

Usando la API de Office 365

Y nada más por hoy, como siempre espero que os resulte interesante, a mi esta nueva versión unificada me ha gustado mucho. Os recomiendo echar un vistazo por todos los enlaces que os he comentado, y ver las oportunidades que nos ofrece esta API, como dije al principio me parecen muy interesantes.

Un saludo a todos.

login-azuread: Un Componente Web con Polymer y Javascript ADAL

Hola a todos,

En la entrada anterior os contaba como se podía usar la librería Javascript ADAL para autenticar una aplicación contra Azure AD usando Javascript y terminaba diciendo que os contaría sobre el componente Polymer que había desarrollado para la autenticación.

Autenticación de nuestra Aplicación usando Javascript ADAL

Lo que he hecho ha sido crear un componente web que permite de una forma sencilla hacer la autenticación y que añadiéndolo a cualquiera de nuestras aplicaciones, podamos gestionar el sign in contra Azure AD de la misma. El código del componente web lo podéis encontrar en mi cuenta de GitHub.

Azuread-login en GitHub

El modo de empleo es muy sencillo, solo tendremos que insertar la siguiente línea en donde queramos tener nuestro modulo de login.

<login-azuread domain="<tenantdomainhere>" clientid="<clientidhere>"
</login-azuread>

Antes, deberemos haber registrado la aplicación en Azure AD, lo que nos proporcionará un client ID. Para que el componente funcione correctamente, deberemos indicar en el atributo domain, el dominio de nuestro tenant y en el atributo clientid el dato obtenido tras el registro de la aplicación en Azure AD.

¿Cuál es el resultado?

Vamos a ver como funciona el componente web una vez lo usamos en un ejemplo.

Cuando un usuario no se ha autenticado.

azureadlogin1

azureadlogin2

Cuando un usuario se ha autenticado
azureadlogin3

Además el componente se ha diseñado de manera que los elementos que lo forman, no se encuentran dentro del Shadow DOM que usa Polymer, sino que están renderizados por el DOM de la página, de manera que podemos estilarlos por medio del CSS de nuestra aplicación. Para ello, solo tenemos que redefinir las clases loginad-name, loginad-a, logoutad-a.

¿Vemos algo de código?

El código es muy sencillo, y aunque lo podéis ver en GitHub os lo pongo aquí y explico algunos detalles. El componente lo forman dos ficheros, uno .html y otro .js

<script src="../../Scripts/polymer.min.js"></script>
<script src="../../Scripts/adal.js"></script>

<polymer-element name="login-azuread" attributes="domain clientID" />
    <template>
        <content select="span"></content>
        <content select="a"></content>
        <content select="a"></content>
    </template>
    <script src="login.js"></script>
</polymer-element>

El fichero .html contiene la definición del componente web. Como véis el template utiliza la etiqueta content, que nos va a permitir que el contenido del componente no esté renderizado en el Shadow DOM y si en el DOM de la página.

window.config = {
    tenant: '',
    clientId: '',
    postLogoutRedirectUri: window.location.origin,
    cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
};

var authContext;

Polymer({
    userName: '',
    domain: '',
    clientID: '',
    ready: function () {
        window.config.tenant = this.domain;
        window.config.clientId = this.clientID;

        authContext = new AuthenticationContext(config);

        var isCallback = authContext.isCallback(window.location.hash);
        authContext.handleWindowCallback();

        if (isCallback &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; !authContext.getLoginError()) {
            window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
        }

        // Check Login Status, Update UI
        var user = authContext.getCachedUser();

        if (user)
            this.userName = user.userName;
        else
            this.userName = '';

    },
    attached: function () {
        var name = document.createElement("span");
        name.innerHTML = this.userName;
        name.className = "loginad-name";

        var login = document.createElement("a");
        login.href = "javascript:;";
        login.innerText = "Login";
        login.className = "loginad-a";
        login.addEventListener("click", this.login, true);

        if (this.userName != '')
            login.style.display = "none";
        else
            login.style.display = "inline-block";

        var logout = document.createElement("a");
        logout.href = "javascript:;";
        logout.innerText = "Logout";
        logout.className = "logoutad-a";
        logout.addEventListener("click", this.logout, true);

        if (this.userName != '')
            logout.style.display = "inline-block";
        else
            logout.style.display = "none";

        this.appendChild(name);
        this.appendChild(login);
        this.appendChild(logout);
    },
    login: function () {
        authContext.login();
    },
    logout: function () {
        authContext.logOut();
    }
});

La particularidad de este código es que, como podemos ver, utiliza la función ready de Polymer para cargar el objeto de configuración y comprobar si está autenticado el usuario y la función attached para inyectar todos los elementos que forman el componente, con la funcionalidad de cada uno.

¿Es mejorable?, como siempre, claro que lo es. Y me encantaría recibir feedback de qué más podríamos hacer para que este componente fuera realmente útil y pudiéramos usarlo en nuestras aplicaciones como una alternativa más.

Saludos, espero que lo hayáis encontrado interesante.

Autenticación de nuestra Aplicación usando Javascript ADAL

Muy buenas a todos,

En una entrada anterior, vimos como podíamos desarrollar una aplicación web con MVC .NET que nos permitiera acceder a la información guardada en nuestro Office 365. Una parte importante de ese desarrollo era la autenticación contra Azure AD, lo que se hacía por medio del paquete Nugget ADAL (Active Directory Authentication Library).

Hace unos días tuve conocimiento de una librería de Javascript que nos permitía hacer la autenticación contra Azure AD (conocida como Javascript ADAL) y que se podía utilizar en el desarrollo de Single Page Applications de una forma muy sencilla. Así que decidí probarlo para seguir abriendo y conociendo el abanico de oportunidades para trabajar contra Azure AD y luego con la API de Office 365. El primer paso obviamente será el login para después acceder y consultar la API usando CORS.

Así que en la entrada de hoy, os voy a mostrar cómo hacer el login usando esta librería de Javascript. Para el ejemplo he creado un proyecto de MVC vacío en el que he hecho todo el desarrollo. Antes de nada, os dejo, como siempre, los enlaces que me han servido de guía y donde creo que hay información muy valiosa sobre esta librería.

http://www.cloudidentity.com/blog/2015/02/19/introducing-adal-js-v1/

https://github.com/AzureADSamples/SinglePageApp-jQuery-DotNet

Disponemos de una versión de la librería integrada con Angularjs y otra versión que podremos usar con JQuery y otros frameworks que será la versión que voy a usar en mi ejemplo.

Empezando con el ejemplo

Obviamente el primer paso en cualquier caso, es registrar nuestra aplicación en el Azure Active Directory de nuestro Tenant. Tras esto, tenemos que descargar el fichero adal.js.

El siguiente paso que he seguido es crear la vista del ejemplo, que es tal y como veréis a continuación

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/Scripts/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <script src="~/Scripts/adal.js"></script>
    <script src="~/Scripts/App/app.js"></script>
</head>
<body>
    <div>
        <h2>Index</h2>

        <a href="javascript:;" class="app-login">Login</a>
        <a href="javascript:;" class="app-logout">Logout</a>
    </div>

</body>
</html>

Esta vista tiene dos botones, uno para hacer login y otro para hacer logout, nada más. El fichero que tiene todo el código es el fichero app.js que podéis ver ahora.

(function () {

    //1.- Initial configuration
    window.config = {
        tenant: '<tentantdomain>',
        clientId: '<clientid>',
        postLogoutRedirectUri: window.location.origin,
        cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
    };
    var authContext = new AuthenticationContext(config);

    //2.- Handle redirect after login
    var isCallback = authContext.isCallback(window.location.hash);
    authContext.handleWindowCallback();

    if (isCallback && !authContext.getLoginError()) {
        window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
    }

    //3.- Check for authenticated information
    var user = authContext.getCachedUser();
    if (user) {
        console.log(user);
    } else {
        console.log("error");
    }

    //4.- Handle events for login & logout
    var $signInButton = $(".app-login");

    $signInButton.click(function () {
        authContext.login();
    });

    var $signOutButton = $(".app-logout");

    $signOutButton.click(function () {
        authContext.logOut();
    });
}());

El código de este ejemplo es una simplificación del ejemplo de Github que os he puesto un poco más arriba y que he usado para entender el proceso que seguía. Lo único que hace este código es mostrar en la consola de depuración los datos del usuario si está logueado o mostrar un texto de error si no lo está. Los puntos más importantes del código son los siguiente:

  1. El primer paso es crear el objeto de configuración, con los datos del tenant y client id que hemos obtenido al registrar la aplicación
  2. A continuación se indica el callback que maneja la redirección después del login
  3. Se comprueba y se muestra la información de logueo del usuario
  4. Por último se crean los eventos que dispararán el login y el logout asociados al click en los enlaces

Y esto es todo, si lo probamos comprobaremos que el resultado es el esperado, cuando no estamos logueados, nos muestra la pantalla de signin de windows para indicar nuestro usuario y contraseña del Azure AD de nuestro tenant.

Lo que os voy a enseñar en próximas entradas es un componente web de Polymer que he creado que utiliza este código para implementar la funcionalidad de signin y signout de una manera muy sencilla y que creo que puede ser de utilidad. Este componente, de hecho ya está en mi GitHub

Un saludo a todos y buen finde.

Registrando una aplicación en Azure Active Directory

Buenas a todos,

Hoy escribo por primera vez sobre un tema relacionado con Azure, aunque espero poco a poco empezar a probar cosas de Azure y poder compartirlas con todos, a medida que vaya aprendiendo. Concretamente, voy a hablar de Azure Active Directory y cómo registrar aplicaciones para permitir que, usuarios de nuestro tenant se autentiquen contra nuestro directorio de azure antes de acceder a la aplicación y también para conceder permisos de la aplicación a las distintas APIs que tenemos disponibles, como puede ser la de Office 365.

Para registrar una aplicación en el Azure AD de nuestro Tenant, vamos a acceder a través del panel de administración de Office 365, ya que, como ya sabréis, tenemos asociados un directorio para nuestro tenant desde el momento en que lo creamos.

Captura de pantalla 2015-03-14 a las 23.03.24

Una vez que entremos en la administración de nuestro tenant, en la sección de “Administración”, hacemos click en Azure AD, lo que nos llevará a nuestra subscripción de Azure, donde podremos administrar el directorio.

Captura de pantalla 2015-03-14 a las 23.04.28

Accedemos al directorio que tenemos creado y a continuación hacemos click en la pestaña de aplicaciones, donde se mostrarán todas las aplicaciones que tenemos registradas, algunas aparecen por defecto, propias de Office 365 y además irán apareciendo las que registremos nosotros mismos.

Captura de pantalla 2015-03-14 a las 23.06.05

Agregaremos una aplicación pulsando el botón Agregar de la parte inferior de la pantalla. A continuación se abre un diálogo donde completaremos la información necesaria para registrar nuestra aplicación en Azure AD.

1.- Indicamos el tipo de acción que queremos realizar

Captura de pantalla 2015-03-14 a las 23.06.19

2.- Indicamos el nombre y tipo de la aplicación

Captura de pantalla 2015-03-14 a las 23.06.46

3.- Establecemos las propiedades de la aplicación que queremos registrar

Captura de pantalla 2015-03-14 a las 23.07.47

Tras indicar las propiedades, finalizamos el proceso de registro de la aplicación

Captura de pantalla 2015-03-14 a las 23.08.02

Si vamos al tab “Configurar” de la pantalla de la aplicación que acabamos de registrar, podremos acceder al ID de Cliente y podemos generar los claves. Ambos datos los usaremos después en el código de nuestra aplicación web para conseguir que ésta funcione correctamente y se autentique con éxito contra Azure AD.

Captura de pantalla 2015-03-14 a las 23.37.37

Con esta ya habremos registrado nuestra aplicación. Este es el primer paso para desarrollar una aplicación que se autentique contra Azure AD y nos conceda acceso a las APIs de Office 365, que será algo que veremos en futuras entradas.

Espero que os sirva, como siempre. Tanto esto como las próximas entradas en las que hablaré de cómo acceder y usar la API de Office 365, han sido los temas con los que me he estado peleando todo el fin de semana  y quería compartir como lo he hecho finalmente.

Un saludo a todos