How to send LTI 1.3 LtiDeepLinkingResponse using .NET Core - asp.net-core

We are struggling to send LtiDeepLinkingResponse using .NET core. Getting Error as {"errors":{"jwt":[{"attribute":"jwt","type":"JWT format is invalid","message":"JWT format is invalid"}]}}
We are referring the solution provided here https://github.com/LtiLibrary/LtiAdvantage
In Code forming a response as
var Token = handler.ReadJwtToken(idToken);
LtiDeepLinkRequest = new LtiDeepLinkingRequest(Token.Payload);
var response = new LtiDeepLinkingResponse
{
Data = LtiDeepLinkRequest.DeepLinkingSettings.Data,
DeploymentId = LtiDeepLinkRequest.DeploymentId
};
var contentItems = new List<ContentItem>();
var customParameters = LtiDeepLinkRequest.Custom;
var platformId = "1000000101";
List<UseCase> selectedUsecases = new List<UseCase>();
selectedUsecases.Add(new UseCase
{
WebGLUrl = "our_web_page.html",
Module = "ModuleName",
Description = "Module Description",
Topics = "Module Topics"
});
foreach (var useCase in selectedUsecases)
{
var url = Url.Page("/Index", null, new { platformId = platformId }, Request.Scheme);
var contentItem = new LtiLinkItem
{
Title = useCase.Module,
Text = useCase.Description,
Url = url,
Custom = new Dictionary<string, string>
{
{ "activity_id", useCase.Id.ToString() }
}
};
if (customParameters != null)
{
foreach (var keyValue in LtiDeepLinkRequest.Custom)
{
contentItem.Custom.TryAdd(keyValue.Key, keyValue.Value);
}
}
contentItems.Add(contentItem);
}
response.ContentItems = contentItems.ToArray();
response.AddClaim(new Claim(JwtRegisteredClaimNames.Iss, LtiDeepLinkRequest.Aud[0]));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Aud, LtiDeepLinkRequest.Iss));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Sub, LtiDeepLinkRequest.Sub));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Iat, EpochTime.GetIntDate(DateTime.UtcNow).ToString()));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Nbf, EpochTime.GetIntDate(DateTime.UtcNow.AddSeconds(-5)).ToString()));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Exp, EpochTime.GetIntDate(DateTime.UtcNow.AddMinutes(5)).ToString()));
response.AddClaim(new Claim(JwtRegisteredClaimNames.Nonce, IdentityModel.CryptoRandom.CreateUniqueId(8)));
RsaSecurityKey key = new RsaSecurityKey(RSA.Create());
key.KeyId = "ourjwkskeyid";
var credentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256);
var header = new JwtHeader(credentials);
var jwt = handler.WriteToken(new JwtSecurityToken(header, response));
return Post("JWT", jwt, LtiDeepLinkRequest.DeepLinkingSettings.DeepLinkReturnUrl);
Other required methods are-
private static ContentResult Post(string name, string value, string url)
{
return new ContentResult
{
Content = "<html><head><title></title></head><body onload=\"document.contentitems.submit()\">"
+ $"<form name=\"contentitems\" method=\"post\" action=\"{url}\">"
+ $"<input type=\"hidden\" name=\"{name}\" value=\"{value}\" /></body></html>",
ContentType = "text/html",
StatusCode = StatusCodes.Status200OK
};
}
We have confirmed that the payload is getting formatted correctly. Payload is
{
  "https://purl.imsglobal.org/spec/lti/claim/message_type": "LtiDeepLinkingResponse",
  "https://purl.imsglobal.org/spec/lti/claim/version": "1.3.0",
  "iss": "1000000101",
  "aud": "https://canvas.instructure.com",
  "exp": "1674104792",
  "iat": "1674104492",
  "nonce": "gdT446jJTgc",
  "azp": "0omiNPx2v5Q",
  "https://purl.imsglobal.org/spec/lti/claim/deployment_id": "11767:105256654",
  "https://purl.imsglobal.org/spec/lti-dl/claim/content_items": [
    {
      "custom": {
        "activity_id": "0"
      },
      "text": "Module Description",
      "title": "ModuleName",
      "type": "ltiResourceLink",
      "url": "our_web_page.html"
    }
  ]
}
Could you please guide what could be missing in this? Or any .NET Core libraries reference from where we can explore how can we send LtiDeepLinkingResponse

Related

Pagination for Google Apps Script with Shopify API

I am running into a bit of a snag setting up pagination in Google Apps Script. I am trying to use it for Shopify API. Reference links attached.
I attached the code below of what I have so far -
trying to figure out how to use the "While" statement to make it check if there is a Next Page URL
trying to figure out a way to parse the Link in the header. Example below. On pages 2+ there will be a next and previous link. We only need the next
https://shop-domain.myshopify.com/admin/api/2019-07/products.json?limit=50&page_info=eyJkaXJlY3Rpb24iOiJwcmV2IiwibGFzdF9pZCI6MTk4NTgyMTYzNCwibGFzdF92YWx1ZSI6IkFjcm9saXRoaWMgQWx1bWludW0gUGVuY2lsIn0%3D; rel="previous", https://shop-domain.myshopify.com/admin/api/2019-07/products.json?limit=50&page_info=eyJkaXJlY3Rpb24iOiJuZXh0IiwibGFzdF9pZCI6MTk4NTgzNjU0NiwibGFzdF92YWx1ZSI6IkFoaXN0b3JpY2FsIFZpbnlsIEtleWJvYXJkIn0%3D; rel="next
function callShopifyOrderCount() {
var accessToken = 'xxxx';
var store_url = 'https://xxxx.myshopify.com/admin/api/2021-01/orders.json?status=any&fields=created_at,id,name,total-price&limit=20';
var headers = {
"Content-Type": "application/json",
'X-Shopify-Access-Token': accessToken
};
var options = {
"method": "GET",
"headers": headers,
"contentType": "application/json",
"muteHttpExceptions": true,
}
var response = UrlFetchApp.fetch(store_url, options)
// Call the link header for next page
var header = response.getHeaders()
var linkHeader = header.Link;
var responseCode = response.getResponseCode();
var responseBody = response.getContentText();
if (responseCode === 200) {
var responseJson = JSON.parse(responseBody);
var objectLength = responseJson.orders.length;
for (var i = 0; i < objectLength; i++) {
var orderId = responseJson.orders[i].id;
var orderPrice = responseJson.orders[i].total_price;
var orderName = responseJson.orders[i].name;
}
} else {
Logger.log(
Utilities.formatString(
"First Request failed. Expected 200, got %d: %s",
responseCode,
responseBody
)
);
// ...
}
// *** NEED TO FIGURE OUT WHILE STATEMENT //
while (Link != null) {
var store_url = linkHeader;
var response = UrlFetchApp.fetch(store_url, options)
var responseCode = response.getResponseCode();
var responseBody = response.getContentText();
var header = response.getHeaders()
var linkHeader = header.Link;
if (responseCode === 200) {
var responseJson = JSON.parse(responseBody);
var objectLength = responseJson.orders.length;
for (var i = 0; i < tweetLength; i++) {
var orderId = responseJson.orders[i].id;
var orderPrice = responseJson.orders[i].total_price;
var orderName = responseJson.orders[i].name;
}
}
else {
Logger.log(
Utilities.formatString(
"Second Request failed. Expected 200, got %d: %s",
responseCode,
responseBody
)
);
}
}
}
References:
https://shopify.dev/tutorials/make-paginated-requests-to-rest-admin-api
https://www.shopify.com/partners/blog/relative-pagination

Bings Ads Script - Calling Google Services not working

I'm trying to run a script in Bing Ads that will get the performance data and write it in Google Sheets. I based my code on Microsoft example: https://learn.microsoft.com/en-us/advertising/scripts/examples/calling-google-services
However, my code won't work.
function main() {
// Set these fields based on the option you chose for getting an access token.
const credentials = {
accessToken: '',
clientId: '',
clientSecret: '',
refreshToken: ''
};
 
// To get a fileId or spreadsheetId, please see
// https://developers.google.com/sheets/api/guides/concepts#spreadsheet_id.
 
// The file must contain a single bid multiplier value (for example,1.1),
// which is used to update keyword bids.
const fileId = 'INSERT FILE ID HERE';
 
// The spreadsheet must contain 3 valid keyword IDs in cells A2, A3, and A4.
const spreadsheetId = 'INSERT SPREADSHEET ID HERE';
// The email address to send a notification email to at the end of the script.
const notificationEmail = 'INSERT EMAIL HERE';
 
var driveApi = GoogleApis.createDriveService(credentials);
 
// Read bid multiplier from the file.
// Reference: https://developers.google.com/drive/api/v3/reference/files/export
var bidMultiplier = driveApi.files.export({ fileId: fileId, mimeType: 'text/csv' }).body;
 
Logger.log(`read bid multiplier ${bidMultiplier}`);
 
var sheetsApi = GoogleApis.createSheetsService(credentials);
 
// Write the old and new bid values back to the spreadsheet.
// Reference: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/batchUpdate
var campaignData = [];
var campaigns = AdsApp.campaigns().withCondition('Cost > 0').forDateRange('THIS_MONTH');
var campaignIterator = campaigns.get();
var iterator = 0;
while(campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
var campaignName = campaign.getName();
var stats = campaign.getStats();
var cost = stats.getCost();
var clicks = stats.getClicks();
var conversions = stats.getConversions();
   var impressions = stats.getImpressions();
campaignData[iterator] = {"CampaignName":campaignName,"cost":cost,"clicks":clicks,"conversions":conversions,"impressions":impressions};
iterator++;
}
var updateResponse = sheetsApi.spreadsheets.values.batchUpdate({ spreadsheetId: spreadsheetId }, {
data: [
{ range: 'A2:G2', values: campaignData.map(x => [x]) },
],
valueInputOption: 'USER_ENTERED'
});
 
Logger.log(`updated ${updateResponse.result.totalUpdatedCells} cells`);
 
var gmailApi = GoogleApis.createGmailService(credentials);
 
var email = [
`To: ${notificationEmail}`,
'Subject: Google Services script',
'',
`You script ran successfully ✓ and updated ${updateResponse.result.totalUpdatedCells} cells.`
].join('\n');
 
// Send the notification email.
// Reference: https://developers.google.com/gmail/api/v1/reference/users/messages/send
var sendResponse = gmailApi.users.messages.send({ userId: 'me' }, { raw: Base64.encode(email) });
 
Logger.log(`sent email thread ${sendResponse.result.threadId}`);
}
 
var GoogleApis;
(function (GoogleApis) {
function createSheetsService(credentials) {
return createService("https://sheets.googleapis.com/$discovery/rest?version=v4", credentials);
}
GoogleApis.createSheetsService = createSheetsService;
 
function createDriveService(credentials) {
return createService("https://www.googleapis.com/discovery/v1/apis/drive/v3/rest", credentials);
}
GoogleApis.createDriveService = createDriveService;
 
function createGmailService(credentials) {
return createService("https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest", credentials);
}
GoogleApis.createGmailService = createGmailService;
 
// Creation logic based on https://developers.google.com/discovery/v1/using#usage-simple
function createService(url, credentials) {
var content = UrlFetchApp.fetch(url).getContentText();
var discovery = JSON.parse(content);
var baseUrl = discovery['rootUrl'] + discovery['servicePath'];
var accessToken = getAccessToken(credentials);
var service = build(discovery, {}, baseUrl, accessToken);
return service;
}
 
function createNewMethod(method, baseUrl, accessToken) {
return (urlParams, body) => {
var urlPath = method.path;
var queryArguments = [];
for (var name in urlParams) {
var paramConfg = method.parameters[name];
if (!paramConfg) {
throw `Unexpected url parameter ${name}`;
}
switch (paramConfg.location) {
case 'path':
urlPath = urlPath.replace('{' + name + '}', urlParams[name]);
break;
case 'query':
queryArguments.push(`${name}=${urlParams[name]}`);
break;
default:
throw `Unknown location ${paramConfg.location} for url parameter ${name}`;
}
}
var url = baseUrl + urlPath;
if (queryArguments.length > 0) {
url += '?' + queryArguments.join('&');
}
var httpResponse = UrlFetchApp.fetch(url, { contentType: 'application/json', method: method.httpMethod, payload: JSON.stringify(body), headers: { Authorization: `Bearer ${accessToken}` }, muteHttpExceptions: true });
var responseContent = httpResponse.getContentText();
var responseCode = httpResponse.getResponseCode();
var parsedResult;
try {
parsedResult = JSON.parse(responseContent);
} catch (e) {
parsedResult = false;
}
var response = new Response(parsedResult, responseContent, responseCode);
if (responseCode >= 200 && responseCode <= 299) {
return response;
}
throw response;
}
}
 
function Response(result, body, status) {
this.result = result;
this.body = body;
this.status = status;
}
Response.prototype.toString = function () {
return this.body;
}
 
function build(discovery, collection, baseUrl, accessToken) {
for (var name in discovery.resources) {
var resource = discovery.resources[name];
collection[name] = build(resource, {}, baseUrl, accessToken);
}
for (var name in discovery.methods) {
var method = discovery.methods[name];
collection[name] = createNewMethod(method, baseUrl, accessToken);
}
return collection;
}
 
function getAccessToken(credentials) {
if (credentials.accessToken) {
return credentials.accessToken;
}
var tokenResponse = UrlFetchApp.fetch('https://www.googleapis.com/oauth2/v4/token', { method: 'post', contentType: 'application/x-www-form-urlencoded', muteHttpExceptions: true, payload: { client_id: credentials.clientId, client_secret: credentials.clientSecret, refresh_token: credentials.refreshToken, grant_type: 'refresh_token' } });
var responseCode = tokenResponse.getResponseCode();
var responseText = tokenResponse.getContentText();
if (responseCode >= 200 && responseCode <= 299) {
var accessToken = JSON.parse(responseText)['access_token'];
return accessToken;
}
throw responseText;
}
})(GoogleApis || (GoogleApis = {}));
 
// Base64 implementation from https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/master/lib/msal-core/src/Utils.ts
class Base64 {
static encode(input) {
const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
let output = "";
let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = this.utf8Encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
}
else if (isNaN(chr3)) {
enc4 = 64;
}
output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
}
return output.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
static utf8Encode(input) {
input = input.replace(/\r\n/g, "\n");
var utftext = "";
for (var n = 0; n < input.length; n++) {
var c = input.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}
}
The first part of the code which brings back values from the spreadsheet works, but when it gets to writing the data in Google Sheets, I get an error and I don't know what it means.
{
"error": {
"code": 404,
"message": "Requested entity was not found.",
"status": "NOT_FOUND"
}
}
at (script code:142:7)

XMLHttpRequest Post in Razor Pages

can some one look at the code and tell me, what Am i doing wrong here? At send, I am getting 400 error.Method downlaodPDF is not even hit.Here is my code.
$('#downloadPDF').on('click', function () {
var token = $("input[name='__RequestVerificationToken']").val();
var vehicle = { "fname": "henry", "lname": "ford" };
var dataJson = JSON.stringify(vehicle);
var req = new XMLHttpRequest();
req.open("POST", "/Test?handler=DownloadPDF");
req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
req.send(dataJson);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
console.log(blob.size);
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="Report_" + new Date() + ".pdf";
link.click(); };
});
public void OnPostDownloadPDF([FromBody]ReportInput input)
{
//My code here
HttpContext.JsReportFeature().Recipe(Recipe.ChromePdf);
}

Can anyone help me out with block.io API for withdrawal of bitcoin from wallet?

I am trying to use block.io API, before few months I tried and implemented, it was working perfect, and now they have changed signed signature method, All APIs working correct, only withdrawal API not working, Response of curl is showing success, but says required more_signatures_needed , I don't know how to do this, Can anyone help me? I will be thankful.
protected void Page_Load(object sender, EventArgs e)
{
myPage.Text = readHtmlPage("https://block.io/api/v2/withdraw_from_addresses/");
//fecth response
String myUri = Session["myPagecc"].ToString();
//display response
Label1.Text = myUri.ToString();
}
private String readHtmlPage(string url)
{
String api_key = "myapikey";
double amounts = "btcamount";
String to_addresses = "receiveraddress";
string FROM_ADDRESS = "myaddress";
string NEWCODE = Guid.NewGuid().ToString().Substring(0, 5);
string priority="medium";
String result = "";
String strPost = "api_key=" + api_key + "&from_addresses=" + FROM_ADDRESS + "&to_addresses="+to_addresses +"&amounts="+amounts+"&priority="+priority+"&nonce="+NEWCODE;
StreamWriter myWriter = null;
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
objRequest.ContentType = "application/x-www-form-urlencoded";
try
{
myWriter = new StreamWriter(objRequest.GetRequestStream());
myWriter.Write(strPost);
}
catch (Exception e)
{
return e.Message;
}
finally
{
myWriter.Close();
}
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
using (StreamReader sr =
new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
return result;
}
"status" : "success", "data" : { "reference_id" : "70ab0922cf036481533e7f345068c0bed36f9681d644d8", "more_signatures_needed" : true, "inputs" : [ { "input_no" : 0, "signatures_needed" : 1, "data_to_sign" : "3916022666e29882298d54c2c8f2ab3306cc4e774594f5db9", "signers" : [ { "signer_address" : "jhE397dsNaNLByJ8WV43emD1mhSpPtwDV", "signer_public_key" : "a34b48a3a18373020d8d96fb53b733d373cd3ba9b5bbfd2c9f8105c8939058130d", "signed_data" : null } ] } ], "encrypted_passphrase" : { "signer_address" : "NaNLmhSByJ8WV43emD1jhE397dspPtwDV", "signer_public_key" : "373cd3ba9b5bbfd2c9f8020d8d96fb53b733d373a34b48a3a18105c8939058130d", "passphrase" : "r20/Wyy5iTVFmpcmn1Y8JOMR8mP7jAqaBrMf2UOW2aEBQSQ1XfxpgonIyFLDOKkmuqH84sETSjXTFsl3dpo5niABB2rL69vnsLbS4DaXMw1o33NH0zgHyzdkAYmIoeGe85YVPMkrQsNhLrGQ6JUaubT+W3rIBxP7rCqYznnMnt8QxG4wu5LSh2EY8fja6AI1" }, "unsigned_tx_hex" : "010000000127d8d4654bc8cf69c9b1980c1afa67e51b5b28241ac080100000023220020200d0c2118ad382e8dab4f3c2ddf5ab8ca1d8ac3ffa3d910a0a2aa86cb69cb77bb62e2a7f12fbc8a699ffffffff076a914103ee4139219756a503842b0ad01000000000019caf5a381440b66bd81188ac64a401000000000017a9145af1577250a83928e306b35f8463047d72d9e3408700000000" } }
Any solution for this please.
With Block.IO token withdrawal it seems we need to send some extra secure pins
as per their doc: https://block.io/api/simple/signing
Like to know how to send cURL to execute ?
Their sample cURL is not working: /api/v2/withdraw_from_addresses/?api_key=API KEY&from_addresses=ADDRESS1,ADDRESS2,...&to_addresses=ADDRESS1,ADDRESS2,...&amounts=AMOUNT1,AMOUNT2,...
response is:
{[status, success]}
{[data, {
"reference_id": "24fe5a.....",
"more_signatures_needed": true,
"inputs": [
{
"input_no": 0,
"signatures_needed": 1,
"data_to_sign": "2498d....",
"signers": [
{
"signer_address": "1H4.....",
"signer_public_key": "037710.....",
"signed_data": null
}
]
}
],
"encrypted_passphrase": {
"signer_address": "1H4...",
"signer_public_key": "0377....",
"passphrase": "fDCM0...."
},
"unsigned_tx_hex": "01000...."
}]}
if possible: expecting some sample in asp.net vb please

Web API 2, Swagger & IdentityServer3

I am trying to setup a Web API with Swagger and an IdentityServer and can't figure out how to make Swagger works correctly.
My React app is working with the IdentityServer and I managed to get the ui working but when I try to activate authentication, I always get a "insufficient_scope" error.
Here's my config :
Client
public static IEnumerable<Client> Get()
{
return new[]
{
new Client
{
ClientId = "ipassportimplicit",
ClientName = "iPassport (Implicit)",
Flow = Flows.Implicit,
AllowAccessToAllScopes = true,
//redirect = URI of the React application callback page
RedirectUris = new List<string>
{
Constants.iPassportReact + "callback.html"
}
},
new Client
{
ClientId = "swaggerui",
ClientName = "Swagger (Implicit)",
Flow = Flows.Implicit,
AllowAccessTokensViaBrowser = true,
PostLogoutRedirectUris = new List<string>
{
"http://localhost:53633/swagger/"
},
AllowAccessToAllScopes = true,
RedirectUris = new List<string>
{
"http://localhost:53633/swagger/ui/o2c-html"
}
}
};
}
Scope
public static IEnumerable<Scope> Get()
{
return new List<Scope>
{
new Scope
{
Name = "passportmanagement",
DisplayName = "Passport Management",
Description = "Allow the application to manage passports on your behalf.",
Type = ScopeType.Resource
},
new Scope
{
Name = "swagger",
DisplayName = "Swagger UI",
Description = "Display Swagger UI",
Type = ScopeType.Resource
}
};
}
SwaggerConfig
public static void Register(HttpConfiguration config)
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
config
.EnableSwagger(c =>
{
c.SingleApiVersion("v2", "api_iPassport");
c.OAuth2("oauth2")
.Description("OAuth2 Implicit Grant")
.Flow("implicit")
.AuthorizationUrl(Constants.iPassportSTSAuthorizationEndpoint)
.TokenUrl(Constants.iPassportSTSTokenEndpoint)
.Scopes(scopes =>
{
scopes.Add("swagger", "Swagger UI");
});
c.OperationFilter<AssignOAuth2SecurityRequirements>();
})
.EnableSwaggerUi(c =>
{
c.EnableOAuth2Support("swaggerui", "swaggerrealm", "Swagger UI");
});
}
Operation Filter
public class AssignOAuth2SecurityRequirements : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any();
if (allowsAnonymous)
return; // must be an anonymous method
//var scopes = apiDescription.ActionDescriptor.GetFilterPipeline()
// .Select(filterInfo => filterInfo.Instance)
// .OfType<AllowAnonymousAttribute>()
// .SelectMany(attr => attr.Roles.Split(','))
// .Distinct();
if (operation.security == null)
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
{
{"oauth2", new List<string> {"swagger"}}
};
operation.security.Add(oAuthRequirements);
}
}
Response Headers
{
"date": "Fri, 12 May 2017 03:37:08 GMT",
"www-authenticate": "Bearer error=\"insufficient_scope\"",
"x-sourcefiles": "=?UTF-8?B?TzpcTG9jYWwgV29ya3NwYWNlXFZTVFMgSUJNXFJlcG9zXFdlYkFQSVxhcGlfaVBhc3Nwb3J0XGFwaV9pUGFzc3BvcnRcYXBpXFVzZXJcR2V0?=",
"server": "Microsoft-IIS/10.0",
"x-powered-by": "ASP.NET",
"content-length": "0",
"content-type": null
}
Anything I can't see? All help appreciated!
Thanks
My problem was in my Startup.cs class of the Web API in which I didn't add the required scope to the
public void ConfigureAuth(IAppBuilder app)
{
var options = new IdentityServerBearerTokenAuthenticationOptions()
{
Authority = Constants.iPassportSTS,
RequiredScopes = new[] { "passportmanagement", "swagger" }
};
app.UseIdentityServerBearerTokenAuthentication(options);
}