Я пытаюсь создать рабочий элемент в DevOps Azure программно, используя OAuth в качестве механизма аутентификации.У пользователей будет форма ввода, в которой будут вводиться тексты, выпадающие списки и т. Д. Для написания описания, выбора Назначено и т. Д. Я получу и использую его для связывания соответствующих полей в DevOps Azure и создания рабочего элемента на имя пользователя.Я передал этот код https://github.com/Microsoft/azure-devops-auth-samples/tree/master/OAuthWebSample/OAuthWebSample/ для реализации OAuth.
Теперь этот код, предоставленный в github, отлично работает как отдельный пользователь.Однако у меня есть некоторые трудности, чтобы объединить его с моим кодом.
Сначала я пишу простой код, взятый из github, который работает нормально, а затем я напишу свой код, который я хочудля интеграции с прежним
Это простой код , где у меня просто есть кнопка в пользовательском интерфейсе (скажем, кнопка «Авторизовать»), которая при нажатии вызывает Authorize ActionResult в OAuthконтроллер.Вот код:
private static readonly Dictionary<Guid, TokenModel> s_authorizationRequests = new Dictionary<Guid, TokenModel>();
public ActionResult Authorize()
{
Guid state = Guid.NewGuid();
s_authorizationRequests[state] = new TokenModel() { IsPending = true };
return new RedirectResult(GetAuthorizationUrl(state.ToString()));
}
TokenModel - это класс, используемый для десериализации Json впоследствии.Отсюда он вызывает метод GetAuthorizationUrl и создает URI.
private static String GetAuthorizationUrl(String state)
{
UriBuilder uriBuilder = new UriBuilder(ConfigurationManager.AppSettings["AuthUrl"]);
var queryParams = HttpUtility.ParseQueryString(uriBuilder.Query ?? String.Empty);
queryParams["client_id"] = ConfigurationManager.AppSettings["ClientAppId"];
queryParams["response_type"] = "Assertion";
queryParams["state"] = state;
queryParams["scope"] = ConfigurationManager.AppSettings["Scope"];
queryParams["redirect_uri"] = ConfigurationManager.AppSettings["CallbackUrl"];
uriBuilder.Query = queryParams.ToString();
return uriBuilder.ToString();
}
Затем он автоматически перенаправляет на метод Callback, который является моим CallbackUrl с кодом авторизации, если пользователь принял Условия, и генерирует маркер доступа, которыйзатем просто передается в представление.
public async Task<ActionResult> Callback(String code, Guid state)
{
String error;
if (ValidateCallbackValues(code, state.ToString(), out error))
{
// Exchange the auth code for an access token and refresh token
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, ConfigurationManager.AppSettings["TokenUrl"]);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Dictionary<String, String> form = new Dictionary<String, String>()
{
{ "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" },
{ "client_assertion", ConfigurationManager.AppSettings["ClientAppSecret"] },
{ "grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer" },
{ "assertion", code },
{ "redirect_uri", ConfigurationManager.AppSettings["CallbackUrl"] }
};
requestMessage.Content = new FormUrlEncodedContent(form);
HttpResponseMessage responseMessage = await s_httpClient.SendAsync(requestMessage);
if (responseMessage.IsSuccessStatusCode)
{
String body = await responseMessage.Content.ReadAsStringAsync();
TokenModel tokenModel = s_authorizationRequests[state];
JsonConvert.PopulateObject(body, tokenModel);
//ViewBag.DeliverableId = WorkItemsHelper.CreateWorkItem(tokenModel.AccessToken);
ViewBag.Token = tokenModel;
}
else
{
error = responseMessage.ReasonPhrase;
}
}
if (!String.IsNullOrEmpty(error))
{
ViewBag.Error = error;
}
ViewBag.ProfileUrl = ConfigurationManager.AppSettings["ProfileUrl"];
return View("TokenView");
}
Эта штука прекрасно работает до сих пор.Но теперь я хочу достичь и попробовать следующее: Теперь я хочу добиться этого с помощью формы ввода, например, (будут другие поля)
<div class="form-row">
<div class="form-group col-md-6">
<label> Title </label>
<input type="text" class="form-control" id="title"/>
</div>
<div class="form-group col-md-6">
<label> Description </label>
<input type="text" class="form-control" id="description"/>
</div>
</div>
<button type="submit" class="btn btn-primary">Save</button>
Когдапользователь нажимает кнопку «Сохранить», я хочу, чтобы генерировался токен доступа, а также использовал этот маркер доступа и поля ввода от пользователя и создавал рабочий элемент в лазурных девопах.Сначала я попробовал ajax-вызов, при котором вызывал метод Authorize при нажатии кнопки сохранения
<script type="text/javascript">
$(document).ready(function () {
$("#testbutton").click(function () {
$.ajax({
type: "post",
url: "/Oauth/Authorize",
success: function (response) {
alert(response);
document.getElementById("returnedmessage").innerHTML = response;
},
error: function () {
alert('an error occured');
}
});
});
});
</script>
(я хотел вернуть Json (ViewBag.TokenModel.AccessToken) из метода Callback).Метод Authorize, но после этого вместо перехода к методу Callback он возвращает ответ с некоторым html, и в консоли моего браузера появляются ошибки, в которых говорится, что 404 не найдено.
Второй подход Iпытаясь следовать нажатию на кнопку «Сохранить», я вызываю метод (скажем, Index) и пытаюсь вызвать внутри него метод Authorize,
public ActionResult Index()
{
var s = Authorize();
return View();
}
Но все равно он не попадает в метод CallBack и ничегослучается.
Есть ли в любом случае, что я могу выполнить свою задачу по одновременному созданию токена доступа и использовать его для создания рабочего элемента, вызывая мой метод с пользовательскими вводами?
Примечание: я хочу избежать другой кнопки, которая явно генерирует токен доступа, и после этого перейти на мою страницу ввода с токеном доступа в качестве скрытого поля или в файлах cookie
Есть ли способчто я могу сделать пользовательский атрибут, такой как атрибут Authorize, который при использовании поверх контроллера проверяет подлинность пользователей перед доступом к каким-либо методам?Или любой другой обходной путь?
Извиняюсь за длинный вопрос или если я не был достаточно ясен.Будем рады любой помощи в мелких деталях.