Как преобразовать Azure cook ie AppServiceAuthSession в действительный токен доступа OAuth JWT? - PullRequest
1 голос
/ 22 января 2020

В Azure У меня есть служба приложений, в которой размещается SPA, и ASP. NET Базовый WebAPI.

Azure Служба приложений

Я активировал Аутентификацию

Аутентификация активна в Сервисе приложений

Когда я пытаюсь получить доступ к SPA, я сначала перенаправляюсь на страницу входа

Логин

После входа в систему устанавливается повар ie (AppServiceAuthSession).

Повар ie 1

Cook ie 2

WebAPI использует промежуточное ПО app.UseAuthentication(); и [Authorize] для защиты API.

Перед тем, как SPA вызывает WebAPI, я преобразовываю Cook ie (AppServiceAuthSession) на токен доступа OAuth с использованием

https://my-app-service.azurewebsites.net/api/values

Это возвращает то, что похоже на access_token.

Token

[{
        "access_token": "PAQABAAAAAABeAFzDwllzTYGDLh_qYbH85B5eMV5PaPELRI_hsnIMx2_pQkgf_TZr-9Z_OC26BOyQqoFM2fR...",
        "id_token": "...",
        "provider_name": "aad",
        "refresh_token": "AQABAAAAAABeAFzDwllzTYGDLh_qYbH8k6pCkZIL4QZzJa06T0AYngu8K2WJV...",
        "user_claims": [{
                "typ": "aud",
                "val": "..."
            }, {
                "typ": "iss",
                "val": "https:\/\/sts.windows.net\/...\/"
            }, {
                "typ": "iat",
                "val": "..."
            }, {
                "typ": "nbf",
                "val": "..."
            }, {
                "typ": "exp",
                "val": "..."
            }, {
                "typ": "aio",
                "val": "..."
            }, {
                "typ": "http:\/\/schemas.microsoft.com\/claims\/authnmethodsreferences",
                "val": "pwd"
            }, {
                "typ": "c_hash",
                "val": "..."
            }, {
                "typ": "ipaddr",
                "val": "..."
            }, {
                "typ": "name",
                "val": "..."
            }, {
                "typ": "nonce",
                "val": "..."
            }, {
                "typ": "http:\/\/schemas.microsoft.com\/identity\/claims\/objectidentifier",
                "val": "..."
            }, {
                "typ": "http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/nameidentifier",
                "val": "..."
            }, {
                "typ": "http:\/\/schemas.microsoft.com\/identity\/claims\/tenantid",
                "val": "..."
            }, {
                "typ": "http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/name",
                "val": "..."
            }, {
                "typ": "http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/upn",
                "val": "..."
            }, {
                "typ": "uti",
                "val": "..."
            }, {
                "typ": "ver",
                "val": "1.0"
            }
        ],
        "user_id": "...@....onmicrosoft.com"
    }
]

Но этот токен, по-видимому, не является JWT.

  1. При использовании этого токена (в заголовке GET «Авторизация»: «Носитель») для вызова API падает с 401 неавторизованным.
  2. Использование декодера, такого как jwt.io fail s.
  3. Токен refre sh не является JWT.
  4. Идентификатор id_token действителен.

Как получить действительный токен доступа JWT от Повар ie AppServiceAuthSession?


Обновление Возможное решение: не пытайтесь преобразовать повара ie в access_token. Скорее выполните обычный запрос аутентификации OAuth2. Azure распознает, что пользователь уже вошел в систему, и возвращает токен доступа (я использую неявный поток, поэтому токен находится в строке запроса URL).

Чтобы вызвать обычный запрос аутентификации, я делаю

var url = config.authorization_endpoint
  + "?response_type=token id_token"
  + "&client_id=" + client_id
  + "&state=" + state
  + "&scope=" + requested_scopes
  + "&redirect_uri=" + redirect_uri
  + "&nonce=" + nonce;

// Redirect to the authorization server
window.location = url;

Ниже находится SPA

var config = {
  client_id: "client_id_hash",
  redirect_uri: "https://my-app-service.azurewebsites.net/index.html",
  authorization_endpoint: "https://login.microsoftonline.com/tenant-id/oauth2/v2.0/authorize",
  token_endpoint: "https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token",
  requested_scopes: "openid api://some-guid/user_impersonation"
};


function generateRandomString() {
  var array = new Uint32Array(28);
  window.crypto.getRandomValues(array);
  return Array.from(array, dec => ('0' + dec.toString(16)).substr(-2)).join('');
}


function parseQueryString(string) {
  if (string == "") { return {}; }
  var segments = string.split("&").map(s => s.split("="));
  var queryString = {};
  segments.forEach(s => queryString[s[0]] = s[1]);
  return queryString;
}

function parseJwt(token) {
  try {
    // Get Token Header
    const base64HeaderUrl = token.split('.')[0];
    const base64Header = base64HeaderUrl.replace('-', '+').replace('_', '/');
    const headerData = JSON.parse(window.atob(base64Header));

    // Get Token payload and date's
    const base64Url = token.split('.')[1];
    const base64 = base64Url.replace('-', '+').replace('_', '/');
    const dataJWT = JSON.parse(window.atob(base64));
    dataJWT.header = headerData;

    return dataJWT;
  } catch (err) {
    return false;
  }
}

function getCookie(cname) {
  var name = cname + "=";
  var decodedCookie = decodeURIComponent(document.cookie);
  var ca = decodedCookie.split(';');
  for (var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return "";
}

function component() {
  const element = document.createElement('div');
  const btn = document.createElement('button');

  const btnApi = document.createElement('button');
  btnApi.innerHTML = 'Call API';
  btnApi.onclick = callAPI;
  element.appendChild(btnApi);

  return element;
}

async function callAPI() {
  console.log('callAPI');
  const data = await fetchValues();
  console.log(data);
  const element = document.createElement('div');
  element.innerHTML = `API response: ${data.toString()}`;
  document.body.appendChild(element);
}

function fetchValues() {

  const accessToken = getCookie('access_token');
  console.log('Access token (from cookie):', accessToken);

  const url = 'https://my-app-service.azurewebsites.net/api/values';
  return fetch(url, {
    headers: {
      "Authorization": "Bearer " + accessToken
    }
  })
    .then((response) => {
      return response.json();
    })
    .then((data) => {
      console.log(data);
      return data;
    });
}

(async function () {
  document.body.appendChild(component());

    const url = "https://my-app-service.azurewebsites.net/.auth/me";
    const response = await fetch(url);
    const data = await response.json();
    const accessToken = data[0].access_token
    const accessTokenJwt = parseJwt(accessToken);

    console.log('accessTokenJwt: ', accessToken, accessTokenJwt);

    document.cookie = "access_token=" + accessToken + "; expires=Fri, 31 Dec 9999 23:59:59 GMT;samesite";




}());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...