Partilhar via


Crie um Suplemento do Office com Node.js que use logon único

Os usuários podem entrar no Office, e o Suplemento Web do Office pode aproveitar esse processo de entrada para autorizá-los a acessar seu suplemento e o Microsoft Graph sem exigir que os eles entrem uma segunda vez. Confira uma visão geral no artigo Habilitar o SSO em um Suplemento do Office.

Este artigo explica-lhe o processo de ativação do início de sessão único (SSO) num suplemento. O suplemento de exemplo que criar tem duas partes; um painel de tarefas que é carregado no Microsoft Excel e um servidor de camada média que processa chamadas para o Microsoft Graph para o painel de tarefas. O servidor de camada média é criado com Node.js e Express e expõe uma única API REST, /getuserfilenames, que devolve uma lista dos primeiros 10 nomes de ficheiro na pasta oneDrive do utilizador. O painel de tarefas utiliza o getAccessToken() método para obter um token de acesso para o utilizador com sessão iniciada no servidor de camada média. O servidor de camada média utiliza o fluxo On-Behalf-Of (OBO) para trocar o token de acesso por um novo com acesso ao Microsoft Graph. Pode expandir este padrão para aceder a quaisquer dados do Microsoft Graph. O painel de tarefas chama sempre uma API REST de camada média (ao transmitir o token de acesso) quando precisa de serviços do Microsoft Graph. A camada média utiliza o token obtido através do OBO para chamar os serviços do Microsoft Graph e devolver os resultados ao painel de tarefas.

Este artigo funciona com um suplemento que utiliza Node.js e Express. Para ler um artigo semelhante sobre um suplemento baseado em ASP.NET, confira Criar um Suplemento do Office com ASP.NET que usa o logon único.

Pré-requisitos

  • Node.js (a versão mais recente de LTS)

  • Git Bash (ou outro cliente Git)

  • Um editor de código - recomendamos Visual Studio Code

  • Pelo menos alguns ficheiros e pastas armazenados no OneDrive for Business na sua subscrição do Microsoft 365

  • Um build do Microsoft 365 que aceita o conjunto de requisitos do IdentityAPI 1.3. Pode qualificar-se para uma subscrição de programador Microsoft 365 E5, que inclui um sandbox de programador, através do Programa para Programadores do Microsoft 365. Para obter detalhes, consulte as FAQ. O sandbox do programador inclui uma subscrição do Microsoft Azure que pode utilizar para registos de aplicações em passos posteriores neste artigo. Se preferir, pode utilizar uma subscrição separada do Microsoft Azure para registos de aplicações. Obtenha uma subscrição de avaliação no Microsoft Azure.

Configure o projeto inicial

  1. Clone ou baixe o repositório em SSO com Suplemento NodeJS do Office.

    Observação

    Há duas versões do exemplo:

    • A pasta Iniciar é um projeto inicial. A interface do usuário e outros aspectos do suplemento que não estão diretamente ligados ao SSO ou à autorização já estão prontos. As próximas seções deste artigo apresentam uma orientação passo a passo para concluir o projeto.
    • A pasta Complete contém o mesmo exemplo com todos os passos de codificação deste artigo concluídos. Para utilizar a versão concluída, basta seguir as instruções neste artigo, mas substituir "Começar" por "Concluído" e ignorar as secções Codificar o lado do cliente e Codificar o lado do servidor de camada média .
  2. Abra uma linha de comandos na pasta Iniciar .

  3. Insira npm install no console para instalar todas as dependências discriminadas no arquivo package.json.

  4. Execute o comando npm run install-dev-certs. Selecione Sim à solicitação para instalar o certificado.

Utilize os seguintes valores para marcadores de posição para os passos de registo de aplicações subsequentes.

Espaço reservado Valor
<add-in-name> Office-Add-in-NodeJS-SSO
<fully-qualified-domain-name> localhost:3000
Permissões do Microsoft Graph perfil, openid, Files.Read

Registar o suplemento com plataforma de identidade da Microsoft

Tem de criar um registo de aplicações no Azure que represente o servidor Web. Isto permite o suporte de autenticação para que os tokens de acesso adequados possam ser emitidos para o código de cliente no JavaScript. Este registo suporta o SSO no cliente e a autenticação de contingência com a Biblioteca de Autenticação da Microsoft (MSAL).

  1. Inicie sessão no portal do Azure com as credenciais de administrador para o seu inquilino do Microsoft 365. Por exemplo, MyName@contoso.onmicrosoft.com.

  2. Selecione Registros de aplicativos. Se não vir o ícone, procure "registo de aplicações" na barra de pesquisa.

    A home page portal do Azure.

    A página Registros de aplicativo é exibida.

  3. Selecione Novo registro.

    Novo registo no painel Registros de aplicativo.

    A página Registrar um aplicativo é exibida.

  4. Na página Registrar um aplicativo, defina os valores da seguinte forma.

    • Defina Nome para <add-in-name>.
    • Defina Tipos de conta suportados como Contas em qualquer diretório organizacional (qualquer diretório Azure AD - multi-inquilino) e contas Microsoft pessoais (por exemplo, Skype, Xbox).
    • Defina o URI de Redirecionamento para utilizar a aplicação de página única (SPA) da plataforma e o URI como https://<fully-qualified-domain-name>/dialog.html.

    Registar um painel de aplicação com o nome e a conta suportada concluídas.

  5. Selecione Registrar. É apresentada uma mensagem a indicar que o registo da aplicação foi criado.

    Mensagem a indicar que o registo da aplicação foi criado.

  6. Copie e guarde os valores do ID da Aplicação (cliente) e do ID do Diretório (inquilino). Use ambos os valores nos procedimentos posteriores.

    Painel de registo de aplicações da Contoso a apresentar o ID de cliente e o ID do diretório.

Adicionar um segredo do cliente

Por vezes denominado palavra-passe de aplicação, um segredo do cliente é um valor de cadeia que a sua aplicação pode utilizar em vez de um certificado para identificar a própria identidade.

  1. No painel esquerdo, selecione Certificados & segredos. Em seguida, no separador Segredos do cliente, selecione Novo segredo do cliente.

    O painel Certificados & segredos.

    É apresentado o painel Adicionar um segredo do cliente .

  2. Adicione uma descrição para o segredo do cliente.

  3. Selecione uma expiração para o segredo ou especifique uma duração personalizada.

    • A duração do segredo do cliente está limitada a dois anos (24 meses) ou menos. Não pode especificar uma duração personalizada superior a 24 meses.
    • A Microsoft recomenda que defina um valor de expiração inferior a 12 meses.

    Adicione um painel de segredos do cliente com a descrição e expira concluído.

  4. Selecione Adicionar. O novo segredo é criado e o valor é apresentado temporariamente.

Importante

Registe o valor do segredo para utilização no código da aplicação cliente. Este valor secreto nunca mais é apresentado depois de sair deste painel.

Expor uma API Web

  1. No painel esquerdo, selecione Expor uma API.

    É apresentado o painel Expor uma API .

    Um registo de aplicação expõe um painel de API.

  2. Selecione Definir para gerar um URI de ID de aplicação.

    Botão Definir no painel Expor uma API do registo de aplicações.

    A secção para definir o URI do ID da aplicação é apresentada com um URI de ID da Aplicação gerado no formulário api://<app-id>.

  3. Atualize o URI do ID da aplicação para api://<fully-qualified-domain-name>/<app-id>.

    Edite o painel URI do ID da Aplicação com a porta localhost definida como 44355.

    • O URI da ID do aplicativo está preenchido previamente com a ID do aplicativo (GUID) no formato api://<app-id>.
    • O formato do URI do ID da aplicação deve ser: api://<fully-qualified-domain-name>/<app-id>
    • Insira entre fully-qualified-domain-nameapi:// e <app-id> (que é um GUID). Por exemplo, api://contoso.com/<app-id>.
    • Se estiver a utilizar localhost, o formato deverá ser api://localhost:<port>/<app-id>. Por exemplo, api://localhost:3000/c6c1f32b-5e55-4997-881a-753cc1d563b7.

    Para obter detalhes adicionais do URI do ID da aplicação, veja Atributo identifierUris do manifesto da aplicação.

    Observação

    Se você receber um erro dizendo que o domínio já pertence a alguém, mas você é o seu proprietário, siga o procedimento em Início Rápido: Adicionar um domínio personalizado ao Azure Active Directory para registrá-lo e, em seguida, repita esta etapa. (Este erro também pode ocorrer se não tiver sessão iniciada com credenciais de um administrador no inquilino do Microsoft 365. Veja o passo 2. Termine sessão e inicie sessão novamente com as credenciais de administrador e repita o processo no passo 3.)

Adicionar um âmbito

  1. Na página Expor uma API , selecione Adicionar um âmbito.

    Selecione Adicionar um botão de âmbito.

    O painel Adicionar um âmbito é aberto.

  2. No painel Adicionar um âmbito , especifique os atributos do âmbito. A tabela seguinte mostra valores de exemplo para e o suplemento do Outlook que requer as profilepermissões , openid, Files.ReadWritee Mail.Read . Modifique o texto para corresponder às permissões que o seu suplemento precisa.

    Campo Descrição Values
    Nome do Escopo O nome do âmbito. Uma convenção de nomenclatura de âmbito comum é resource.operation.constraint. Para O SSO, tem de ser definido como access_as_user.
    Quem pode consentir Determina se o consentimento do administrador é necessário ou se os utilizadores podem consentir sem uma aprovação de administrador. Para aprender SSO e exemplos, recomendamos que defina esta opção para Administradores e utilizadores.

    Selecione Administradores apenas para permissões com privilégios mais elevados.
    Administração o nome a apresentar do consentimento Uma breve descrição da finalidade do âmbito visível apenas para os administradores. Read/write permissions to user files. Read permissions to user mail and profiles.
    descrição do consentimento do Administração Uma descrição mais detalhada da permissão concedida pelo âmbito que apenas os administradores veem. Allow Office to have read/write permissions to all user files and read permissions to all user mail. Office can call the app's web APIs as the current user.
    Nome a apresentar do consentimento do utilizador Uma breve descrição da finalidade do âmbito. Mostrado aos utilizadores apenas se definir Quem pode dar consentimento a Administradores e utilizadores. Read/write permissions to your files. Read permissions to your mail and profile.
    Descrição do consentimento do utilizador Uma descrição mais detalhada da permissão concedida pelo âmbito. Mostrado aos utilizadores apenas se definir Quem pode dar consentimento a Administradores e utilizadores. Allow Office to have read/write permissions to your files, and read permissions to your mail and profile.
  3. Defina o Estado como Ativado e, em seguida, selecione Adicionar âmbito.

    Defina o estado como ativado e selecione o botão adicionar âmbito.

    O novo âmbito que definiu é apresentado no painel.

    O novo âmbito apresentado no painel Expor uma API.

    Observação

    A parte de domínio do Nome de escopo exibidos logo abaixo do campo de texto deve corresponder automaticamente ao URI de ID do aplicativo definidos na etapa anterior com /access_as_user acrescentado ao final; por exemplo, api://localhost:6789/c6c1f32b-5e55-4997-881a-753cc1d563b7/access_as_user.

  4. Selecione Adicionar um aplicativo cliente.

    Selecione Adicionar uma aplicação cliente.

    É apresentado o painel Adicionar uma aplicação cliente .

  5. No ID de Cliente, introduza ea5a67f6-b6f3-4338-b240-c655ddc3cc8e. Este valor pré-autoriza todos os pontos finais de aplicações do Microsoft Office. Se também pretender pré-autorizar o Office quando utilizado no Microsoft Teams, adicione 1fec8e78-bce4-4aaf-ab1b-5451cc387264 (Ambiente de trabalho do Microsoft Teams e Teams para dispositivos móveis) e 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 (Teams na Web).

    Observação

    O ea5a67f6-b6f3-4338-b240-c655ddc3cc8e ID pré-autoriza o Office em todas as seguintes plataformas. Em alternativa, pode introduzir um subconjunto adequado dos seguintes IDs se, por qualquer motivo, quiser negar a autorização ao Office em algumas plataformas. Se o fizer, deixe de fora os IDs das plataformas a partir das quais pretende reter a autorização. Os utilizadores do seu suplemento nessas plataformas não poderão chamar as suas APIs Web, mas outras funcionalidades no seu suplemento continuarão a funcionar.

    • d3590ed6-52b3-4102-aeff-aad2292ab01c (Microsoft Office)
    • 93d53678-613d-4013-afc1-62e9e444a0a5(Office na Web)
    • bc59ab01-8403-45c6-8796-ac3ef710b3e3(Outlook na Web)
  6. Em Âmbitos autorizados, selecione a caixa api://<fully-qualified-domain-name>/<app-id>/access_as_user de verificação.

  7. Selecione Adicionar aplicativo.

    O painel Adicionar uma aplicação cliente.

Adicionar permissões do Microsoft Graph

  1. No painel esquerdo, selecione Permissões da API.

    O painel permissões da API.

    O painel permissões da API é aberto.

  2. Selecione Adicionar uma permissão.

    Adicionar uma permissão no painel de permissões da API.

    O painel Pedir permissões da API é aberto.

  3. Selecione Microsoft Graph.

    O painel Pedir permissões da API com o botão Microsoft Graph.

  4. Selecione Permissões delegadas.

    O painel Pedir permissões da API com o botão permissões delegadas.

  5. Na caixa de pesquisa Selecionar permissões , procure as permissões de que o suplemento precisa. Por exemplo, para um suplemento do Outlook, pode utilizar profile, openid, Files.ReadWritee Mail.Read.

    Observação

    A permissão User.Read pode já estar listada por padrão. É uma boa prática pedir apenas as permissões necessárias, pelo que recomendamos que desmarque a caixa para esta permissão se o seu suplemento não precisar realmente da mesma.

  6. Selecione a caixa de verificação para cada permissão tal como é apresentada. Tenha em atenção que as permissões não permanecerão visíveis na lista à medida que seleciona cada uma delas. Depois de selecionar as permissões de que o suplemento precisa, selecione Adicionar permissões.

    O painel Pedir permissões da API com algumas permissões selecionadas.

  7. Selecione Conceder consentimento do administrador para [nome do inquilino]. Selecione Sim para a confirmação apresentada.

Configurar a versão do token de acesso

Você deve definir a versão do token de acesso aceitável para seu aplicativo. Esta configuração é efetuada no manifesto da aplicação do Azure Active Directory.

Definir a versão do token de acesso

A versão do token de acesso pode ser alterada se escolher um tipo de conta diferente de Contas em qualquer diretório organizacional (Qualquer diretório Azure AD - Multi-inquilino) e contas Microsoft pessoais (por exemplo, Skype, Xbox). Utilize os seguintes passos para garantir que a versão do token de acesso está correta para a utilização do SSO do Office.

  1. No painel esquerdo, selecione Manifesto.

    Selecione Manifesto do Azure.

    É apresentado o manifesto da aplicação do Azure Active Directory.

  2. Insira 2 como o valor da propriedade accessTokenAcceptedVersion.

    Valor para a versão do token de acesso aceite.

  3. Selecione Salvar.

    Uma mensagem é exibida no navegador informando que o manifesto foi atualizado com êxito.

    Mensagem atualizada do manifesto.

Parabéns! Concluiu o registo de aplicações para ativar o SSO para o seu suplemento do Office.

Configurar o suplemento

  1. Abra a pasta \Begin no projeto clonado no editor de códigos.

  2. Abra o .ENV ficheiro e utilize os valores que copiou anteriormente do registo da aplicação Office-Add-in-NodeJS-SSO . Defina os valores da seguinte forma:

    Nome Valor
    CLIENT_ID ID da aplicação (cliente) na página de descrição geral do registo de aplicações.
    CLIENT_SECRET Segredo do cliente guardado na página Certificados & Segredos .

    Os valores não devem estar entre aspas. Quando terminar, o arquivo deverá ser semelhante ao seguinte:

    CLIENT_ID=8791c036-c035-45eb-8b0b-265f43cc4824
    CLIENT_SECRET=X7szTuPwKNts41:-/fa3p.p@l6zsyI/p
    NODE_ENV=development
    SERVER_SOURCE=<https://localhost:3000>
    
  3. Abra o arquivo de manifesto de suplemento "manifest\ manifest_local.xml" e role até a parte inferior do arquivo. Logo acima da </VersionOverrides> etiqueta de fim, encontrará a seguinte marcação.

    <WebApplicationInfo>
      <Id>$app-id-guid$</Id>
      <Resource>api://localhost:3000/$app-id-guid$</Resource>
      <Scopes>
          <Scope>Files.Read</Scope>
          <Scope>profile</Scope>
          <Scope>openid</Scope>
      </Scopes>
    </WebApplicationInfo>
    
  4. Substitua o marcador de posição "$app-id-guid$" em ambos os locais na marcação pelo ID da Aplicação que copiou quando criou o registo da aplicação Office-Add-in-NodeJS-SSO . Os símbolos "$" não fazem parte do ID, por isso não os inclua. Este é o mesmo ID que utilizou para o CLIENT_ID no . Ficheiro ENV.

    Observação

    O <Valor do recurso> é o URI do ID da Aplicação que definiu quando registou o suplemento. A <secção Âmbitos> é utilizada apenas para gerar uma caixa de diálogo de consentimento se o suplemento for vendido através do AppSource.

  5. Abra o arquivo \public\javascripts\fallback-msal\authConfig.js. Substitua o marcador de posição "$app-id-guid$" pelo ID da aplicação que guardou no registo da aplicação Office-Add-in-NodeJS-SSO que criou anteriormente.

  6. Salve as alterações no arquivo.

Codificar o lado do cliente

Chamar a nossa API REST do servidor Web

  1. No editor de códigos, abra o arquivo public\javascripts\ssoAuthES6.js. Já tem código que garante que as Promessas são suportadas, mesmo no controlo webview Trident (Internet Explorer 11) e uma Office.onReady chamada para atribuir um processador ao único botão do suplemento.

    Observação

    Como o nome sugere, o ssoAuthES6.js usa a sintaxe JavaScript ES6, pois usar async e await mostra melhor a simplicidade fundamental da API de SSO. Quando o servidor localhost é iniciado, este ficheiro é transpiado para a sintaxe ES5 para que o exemplo suporte Trident.

  2. Na função getFileNameList, substitua TODO 1 pelo seguinte código. Sobre este código, observe:

    • A função getFileNameList é chamada quando o utilizador escolhe o botão Obter Nomes de Ficheiros do OneDrive no painel de tarefas.
    • Chama a callWebServerAPI função especificando a API REST a chamar. Isto devolve JSON contendo uma lista de nomes de ficheiros do OneDrive do utilizador.
    • O JSON é transmitido para a writeFileNamesToOfficeDocument função para listar os nomes de ficheiro no documento.
    try {
        const jsonResponse = await callWebServerAPI('GET', '/getuserfilenames');
        if (jsonResponse === null) {
            // Null is returned when a message was displayed to the user
            // regarding an authentication error that cannot be resolved.
            return;
        }
        await writeFileNamesToOfficeDocument(jsonResponse);
        showMessage('Your OneDrive filenames are added to the document.');
    } catch (error) {
        console.log(error.message);
        showMessage(error.message);
    }
    
  3. Na função callWebServerAPI, substitua TODO 2 pelo seguinte código. Sobre este código, observe:

    • A função chama getAccessToken qual é a nossa própria função que encapsula com o SSO do Office ou a contingência MSAL conforme necessário para obter o token. Se devolver um token nulo, foi apresentada uma mensagem para uma condição de erro de autenticação que não pode ser resolvida, pelo que a função também devolve nulo.
    • A função utiliza a fetch API para chamar o servidor Web e, se tiver êxito, devolve o corpo JSON.
    const accessToken = await getAccessToken(authSSO);
    if (accessToken === null) {
        return null;
    }
    const response = await fetch(path, {
        method: method,
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + accessToken,
        },
    });
    
    // Check for success condition: HTTP status code 2xx.
    if (response.ok) {
        return response.json();
    }
    
  4. Na função callWebServerAPI, substitua TODO 3 pelo seguinte código. Sobre este código, observe:

    • Este código processa o cenário em que o token de SSO expirou. Em caso afirmativo, temos de ligar Office.auth.getAccessToken para obter um token atualizado. A forma mais simples é fazer uma chamada recursiva que resulta numa nova chamada para Office.auth.getAccessToken. O retryRequest parâmetro garante que a chamada recursiva só é tentada uma vez.
    • A TokenExpiredError cadeia é definida pelo nosso servidor Web sempre que deteta um token expirado.
     // Check for fail condition: Is SSO token expired? If so, retry the call which will get a refreshed token.
    const jsonBody = await response.json();
    if (
        authSSO === true &&
        jsonBody != null &&
        jsonBody.type === 'TokenExpiredError'
    ) {
        if (!retryRequest) {
            return callWebServerAPI(method, path, true); // Try the call again. The underlying call to Office JS getAccessToken will refresh the token.
        } else {
            // Indicates a second call to retry and refresh the token failed.
            authSSO = false;
            return callWebServerAPI(method, path, true); // Try the call again, but now using MSAL fallback auth.
        }
    }
    
  5. Na função callWebServerAPI, substitua TODO 4 pelo seguinte código. Sobre este código, observe:

    • A Microsoft Graph cadeia é definida pelo nosso servidor Web sempre que uma chamada do Microsoft Graph falha.
    // Check for fail condition: Did we get a Microsoft Graph API error, which is returned as bad request (403)?
    if (response.status === 403 && jsonBody.type === 'Microsoft Graph') {
        throw new Error('Microsoft Graph error: ' + jsonBody.errorDetails);
    }
    
  6. Na função callWebServerAPI, substitua TODO 5 pelo seguinte código.

    // Handle other errors.
    throw new Error(
        'Unknown error from web server: ' + JSON.stringify(jsonBody)
    );
    
  7. Na função getAccessToken, substitua TODO 6 pelo seguinte código. Sobre este código, observe:

    • authSSO monitoriza se estivermos a utilizar o SSO ou a utilizar a contingência MSAL. Se o SSO for utilizado, a função chama Office.auth.getAccessToken e devolve o token.
    • Os erros são processados pela handleSSOErrors função que devolverá um token se mudar para a autenticação MSAL de contingência.
    • A autenticação de contingência utiliza a biblioteca MSAL para iniciar sessão no utilizador. O suplemento em si é um SPA e utiliza um registo de aplicação SPA para aceder ao servidor Web.
    if (authSSO) {
        try {
            // Get the access token from Office host using SSO.
            // Note that Office.auth.getAccessToken modifies the options parameter. Create a copy of the object
            // to avoid modifying the original object.
            const options = JSON.parse(JSON.stringify(ssoOptions));
            const token = await Office.auth.getAccessToken(options);
            return token;
        } catch (error) {
            console.log(error.message);
            return handleSSOErrors(error);
        }
    } else {
        // Get access token through MSAL fallback.
        try {
            const accessToken = await getAccessTokenMSAL();
            return accessToken;
        } catch (error) {
            console.log(error);
            throw new Error(
                'Cannot get access token. Both SSO and fallback auth failed. ' +
                    error
            );
        }
    }
    
  8. Na função handleSSOErrors, substitua TODO 7 pelo seguinte código. Para saber mais sobre esses erros, confira Solucionar problemas de SSO em suplementos do Office em.

    switch (error.code) {
        case 13001:
            // No one is signed into Office. If the add-in cannot be effectively used when no one
            // is logged into Office, then the first call of getAccessToken should pass the
            // `allowSignInPrompt: true` option. Since this sample does that, you should not see
            // this error.
            showMessage(
                'No one is signed into Office. But you can use many of the add-ins functions anyway. If you want to log in, press the Get OneDrive File Names button again.'
            );
            break;
        case 13002:
            // The user aborted the consent prompt. If the add-in cannot be effectively used when consent
            // has not been granted, then the first call of getAccessToken should pass the `allowConsentPrompt: true` option.
            showMessage(
                'You can use many of the add-ins functions even though you have not granted consent. If you want to grant consent, press the Get OneDrive File Names button again.'
            );
            break;
        case 13006:
            // Only seen in Office on the web.
            showMessage(
                'Office on the web is experiencing a problem. Please sign out of Office, close the browser, and then start again.'
            );
            break;
        case 13008:
            // Only seen in Office on the web.
            showMessage(
                'Office is still working on the last operation. When it completes, try this operation again.'
            );
            break;
        case 13010:
            // Only seen in Office on the web.
            showMessage(
                "Follow the instructions to change your browser's zone configuration."
            );
            break;
    
  9. Substitua TODO 8 pelo código a seguir. Para quaisquer erros que não possam ser processados, o código muda para a autenticação de contingência com MSAL.

    default: //recursive call.
            // For all other errors, including 13000, 13003, 13005, 13007, 13012, and 50001, fall back
            // to MSAL sign-in.
            showMessage('SSO failed. Trying fallback auth.');
            authSSO = false;
            return getAccessToken(false);
    }
    return null; // Return null for errors that show a message to the user.
    

Codificar a API REST do servidor Web

O servidor Web fornece APIs REST para o cliente chamar. Por exemplo, a API /getuserfilenames REST obtém uma lista de nomes de ficheiro da pasta do OneDrive do utilizador. Cada chamada à API REST requer um token de acesso do cliente para garantir que o cliente correto está a aceder aos respetivos dados. O token de acesso é trocado por um token do Microsoft Graph através do fluxo On-Behalf-Of (OBO). O novo token do Microsoft Graph é colocado em cache pela biblioteca MSAL para chamadas à API subsequentes. Nunca é enviado para fora do servidor Web. Para obter mais informações, veja Pedido de token de acesso de camada média

Criar a rota e implementar o fluxo On-Behalf-Of

  1. Abra o ficheiro routes\getFilesRoute.js e substitua TODO 9 pelo seguinte código. Sobre este código, observe:

    • Chama .authHelper.validateJwt Isto garante que o token de acesso é válido e não foi adulterado.
    • Para obter mais informações, veja Validar tokens.
    router.get(
     "/getuserfilenames",
     authHelper.validateJwt,
     async function (req, res) {
       // TODO 10: Exchange the access token for a Microsoft Graph token
       //          by using the OBO flow.
     }
    );
    
  2. Substitua TODO 10 pelo código a seguir. Sobre este código, observe:

    • Apenas pede os âmbitos mínimos de que precisa, como files.read.
    • Utiliza a MSAL authHelper para executar o fluxo OBO na chamada para acquireTokenOnBehalfOf.
    try {
      const authHeader = req.headers.authorization;
      let oboRequest = {
        oboAssertion: authHeader.split(' ')[1],
        scopes: ["files.read"],
      };
    
      // The Scope claim tells you what permissions the client application has in the service.
      // In this case we look for a scope value of access_as_user, or full access to the service as the user.
      const tokenScopes = jwt.decode(oboRequest.oboAssertion).scp.split(' ');
      const accessAsUserScope = tokenScopes.find(
        (scope) => scope === 'access_as_user'
      );
      if (!accessAsUserScope) {
        res.status(401).send({ type: "Missing access_as_user" });
        return;
      }
      const cca = authHelper.getConfidentialClientApplication();
      const response = await cca.acquireTokenOnBehalfOf(oboRequest);
      // TODO 11: Call Microsoft Graph to get list of filenames.
    } catch (err) {
      // TODO 12: Handle any errors.
    }
    
  3. Substitua TODO 11 pelo código a seguir. Sobre este código, observe:

    • Constrói o URL da chamada do Microsoft API do Graph e, em seguida, faz a chamada através da getGraphData função .
    • Devolve erros ao enviar uma resposta HTTP 500 juntamente com detalhes.
    • Com êxito, devolve o JSON com a lista de nome de ficheiro ao cliente.
    // Minimize the data that must come from MS Graph by specifying only the property we need ("name")
    // and only the top 10 folder or file names.
    const rootUrl = '/me/drive/root/children';
    
    // Note that the last parameter, for queryParamsSegment, is hardcoded. If you reuse this code in
    // a production add-in and any part of queryParamsSegment comes from user input, be sure that it is
    // sanitized so that it cannot be used in a Response header injection attack.
    const params = '?$select=name&$top=10';
    
    const graphData = await getGraphData(
      response.accessToken,
      rootUrl,
      params
    );
    
    // If Microsoft Graph returns an error, such as invalid or expired token,
    // there will be a code property in the returned object set to a HTTP status (e.g. 401).
    // Return it to the client. On client side it will get handled in the fail callback of `makeWebServerApiCall`.
    if (graphData.code) {
      res
        .status(403)
        .send({
          type: "Microsoft Graph",
          errorDetails:
            "An error occurred while calling the Microsoft Graph API.\n" +
            graphData,
        });
    } else {
      // MS Graph data includes OData metadata and eTags that we don't need.
      // Send only what is actually needed to the client: the item names.
      const itemNames = [];
      const oneDriveItems = graphData["value"];
      for (let item of oneDriveItems) {
        itemNames.push(item["name"]);
      }
    
      res.status(200).send(itemNames);
    }
    // TODO 12: Check for expired token.
    
  4. Substitua TODO 12 pelo código a seguir. Este código verifica especificamente se o token expirou porque o cliente pode pedir um novo token e chamar novamente.

    } catch (err) {
       // On rare occasions the SSO access token is unexpired when Office validates it,
       // but expires by the time it is used in the OBO flow. Microsoft identity platform will respond
       // with "The provided value for the 'assertion' is not valid. The assertion has expired."
       // Construct an error message to return to the client so it can refresh the SSO token.
       if (err.errorMessage.indexOf('AADSTS500133') !== -1) {
         res.status(401).send({ type: "TokenExpiredError", errorDetails: err });
       } else {
         res.status(403).send({ type: "Unknown", errorDetails: err });
       }
    }
    

O exemplo tem de processar a autenticação de contingência através da autenticação MSAL e SSO através do Office. O exemplo irá experimentar primeiro o SSO e o authSSO booleano na parte superior do ficheiro controla se o exemplo está a utilizar o SSO ou mudou para autenticação de contingência.

Executar o projeto

  1. Certifique-se de ter alguns arquivos no seu OneDrive para que você possa verificar os resultados.

  2. Abra um aviso de comando na raiz da pasta \Begin.

  3. Execute o comando npm install para instalar todas as dependências do pacote.

  4. Execute o comando npm start para iniciar o servidor de camada média.

  5. Você deve fazer o sideload do suplemento em um aplicativo do Office (Excel, Word ou PowerPoint) para testá-lo. As instruções dependem da plataforma. Há links para instruções no Fazer sideload de suplemento para teste.

  6. No aplicativo do Office, na faixa de opções Home, selecione o botão Mostrar suplemento no grupoSSO Node.js para abrir o suplemento do painel de tarefas.

  7. Clique no botão Definir Nome de Arquivos do One Drive. Se tiver sessão iniciada no Office com uma conta Microsoft 365 Education ou profissional ou uma conta Microsoft e o SSO estiver a funcionar conforme esperado, os primeiros 10 nomes de ficheiros e pastas no seu OneDrive for Business são inseridos no documento. (A primeira vez pode demorar até 15 segundos.) Se não tiver sessão iniciada ou se estiver num cenário que não suporta SSO ou se o SSO não estiver a funcionar por qualquer motivo, ser-lhe-á pedido para iniciar sessão. Depois de iniciar sessão, os nomes dos ficheiros e pastas são apresentados.

Observação

Se você entrou no Office com uma ID diferente e se alguns aplicativos do Office que estavam abertos no momento continuam abertos, o Office pode não alterar de forma confiável sua ID, mesmo que pareça ter feito isso. Se isso acontecer, a chamada para o Microsoft Graph pode falhar ou os dados da ID anterior podem ser retornados. Para evitar isso, certifique-se de fechar todos os outros aplicativos do Office antes de pressionar Obter nomes de arquivos do OneDrive.

Parar a execução do projeto

Quando estiver pronto para parar o servidor de camada média e desinstalar o suplemento, siga estas instruções:

  1. Execute o seguinte comando para parar o servidor de camada média.

    npm stop
    
  2. Para desinstalar ou remover o suplemento, veja o artigo de sideload específico que utilizou para obter detalhes.

Notas de segurança

  • A /getuserfilenames rota em getFilesroute.js utiliza uma cadeia literal para compor a chamada para o Microsoft Graph. Se alterar a chamada para que qualquer parte da cadeia seja proveniente da entrada do utilizador, desinsite a entrada para que não possa ser utilizada num ataque de injeção de cabeçalho de resposta.

  • Na app.js seguinte política de segurança de conteúdos está implementada para scripts. Poderá querer especificar restrições adicionais consoante as suas necessidades de segurança do suplemento.

    "Content-Security-Policy": "script-src https://appsforoffice.microsoft.com https://ajax.aspnetcdn.com https://alcdn.msauth.net " + process.env.SERVER_SOURCE,

Siga sempre as melhores práticas de segurança na documentação plataforma de identidade da Microsoft.