Closed mountaingeru closed 4 months ago
You are sending a POST request which will require an antiforgery token. Another option with graphql is to use GET requests, which is documented here: https://docs.orchardcore.net/en/dev/docs/reference/modules/Apis.GraphQL/#get-request
Thank you very much for your answer and I am sorry I was late in answering.
I have create a MVC project and included the following code in ConfigureServices
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = "https://localhost:44396/connect/token";
options.ClientId = "e0f660a2cf2a47babac40a4a8c24e7e0";
options.ClientSecret = "76945d3917a4456db5a41fc2949d6439";
options.ResponseType = "code id_token";
options.RequireHttpsMetadata = false;
options.GetClaimsFromUserInfoEndpoint = true;
});
I include the js code to fetch the GraphQL API using a POST request. I tried several combinations
const opts = {
method: "POST",
mode: 'no-cors',
credentials: 'include',
//headers: { "Content-Type": "application/json" },
headers: { "Content-Type": "application/graphql" },
//body: JSON.stringify({query: myQuery1})
body: JSON.stringify({ query: myQuery1 })
//body: JSON.stringify({ "query": myQuery1 })
//body: myQuery1
};.
In the developer tools of the brower I see three cookies related to authoritation: orchauth_Default, orchantiforgery_Default and .AspNetCore.Antiforgery.QrPYhbOUQ0o.
The request fetched seems to include the authoritation cookies information:
General Request URL: https://localhost:44396/api/graphql Request Method: POST Status Code: 500 Internal Server Error Remote Address: [::1]:44396 Referrer Policy: no-referrer-when-downgrade
Response Headers Content-Length: 4962 Content-Type: text/plain Date: Sat, 30 May 2020 14:33:42 GMT Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET
Request Headers Accept: / Accept-Encoding: gzip, deflate, br Accept-Language: en,es-ES;q=0.9,es;q=0.8 Cache-Control: no-cache Connection: keep-alive Content-Length: 396 Content-Type: text/plain;charset=UTF-8 Cookie: _ga=GA1.1.625725641.1589660747; .AspNetCore.Antiforgery.QrPYhbOUQ0o=CfDJ8GAc_xY9fJ...; orchantiforgery_Default=CfDJ8Nx_bbMNqvtLnrArzxb7Ojys...; orchauth_Default=CfDJ8Nx_bbMNqvtLnrArzxb7Oj... Host: localhost:44396 Origin: https://localhost:44326 Pragma: no-cache Referer: https://localhost:44326/ Sec-Fetch-Dest: empty Sec-Fetch-Mode: no-cors Sec-Fetch-Site: same-site User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
And the response is:
System.NullReferenceException: Object reference not set to an instance of an object. at OrchardCore.Apis.GraphQL.GraphQLMiddleware.ExecuteAsync(HttpContext context, ISchemaFactory schemaService) in C:\projects\orchardcore\src\OrchardCore.Modules\OrchardCore.Apis.GraphQL\GraphQLMiddleware.cs:line 146 at OrchardCore.Apis.GraphQL.GraphQLMiddleware.Invoke(HttpContext context, IAuthorizationService authorizationService, IAuthenticationService authenticationService, ISchemaFactory schemaService) in C:\projects\orchardcore\src\OrchardCore.Modules\OrchardCore.Apis.GraphQL\GraphQLMiddleware.cs:line 70 at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at OrchardCore.Diagnostics.DiagnosticsStartupFilter.<>c__DisplayClass3_0.<
b__1>d.MoveNext() in C:\projects\orchardcore\src\OrchardCore.Modules\OrchardCore.Diagnostics\DiagnosticsStartupFilter.cs:line 47 --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context) at OrchardCore.Modules.ModularTenantRouterMiddleware.Invoke(HttpContext httpContext) in C:\projects\orchardcore\src\OrchardCore\OrchardCore\Modules\ModularTenantRouterMiddleware.cs:line 83 at OrchardCore.Environment.Shell.Scope.ShellScope.UsingAsync(Func`2 execute) in C:\projects\orchardcore\src\OrchardCore\OrchardCore.Abstractions\Shell\Scope\ShellScope.cs:line 103 at OrchardCore.Modules.ModularTenantContainerMiddleware.Invoke(HttpContext httpContext) in C:\projects\orchardcore\src\OrchardCore\OrchardCore\Modules\ModularTenantContainerMiddleware.cs:line 61 at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) HEADERS
Accept: / Accept-Encoding: gzip, deflate, br Accept-Language: en,es-ES;q=0.9,es;q=0.8 Cache-Control: no-cache Connection: keep-alive Content-Length: 396 Content-Type: text/plain;charset=UTF-8 Cookie: _ga=GA1.1.625725641.1589660747; .AspNetCore.Antiforgery.QrPYhbOUQ0o=CfDJ8GAc_xY9fJ...; orchantiforgery_Default=CfDJ8Nx_bbMNqvtLnrArzxb7Ojys...; orchauth_Default=CfDJ8Nx_bbMNqvtLnrArzxb7Oj... Host: localhost:44396 Pragma: no-cache Referer: https://localhost:44326/ User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Origin: https://localhost:44326 Sec-Fetch-Site: same-site Sec-Fetch-Mode: no-cors Sec-Fetch-Dest: empty
However, making the request from Postman (including the Bearer token I get by requesting https://localhost:44396/connect/token) everything goes fine.
I also tried with the GET request. Everything goes fine with Postman but does not work when fetching from JavaScript.
Any idea about what I am doing wrong? I am kind of stuck
I am sorry if the question is silly, but I am new at these things. Thanks in advance!
Is your website the same one that is running the graphql service? You need to be authenticated to do the queries. Unless you allow "Anonymous" to run the queries. I believe that in the case of Postman there is a valid auth cookie, but not as the user of your app.
We might want to create a guide showing how to configure an implement openid such that we can use apis from a web app.
The graphql service and the website are different web apps. We tried hosting them in the same server and in different servers.
After many attempts and thanks to the collaboration of a colleague we achieved a satisfactory solution. We don't solve everything in javascript, but the way it works is fine for us. Here is what we have done (assuming we included things that could be done better):
We followed this guide (https://medium.com/swlh/orchard-core-open-id-connect-and-graphql-f003a222260a) to configure OpenId.
We create our Net Core MVC app.
We include a service to get the token used in the GraphQL request.
public class TokenService : ITokenService
{
private readonly IHttpClientFactory _clientFactory;
private readonly IOptions<OrchardConfig> _config;
public TokenService(IOptions<OrchardConfig> config)
{
_config = config;
}
public async Task<string> GetTokenAsync()
{
IList<KeyValuePair<string, string>> nameValueCollection = new List<KeyValuePair<string, string>> {
{ new KeyValuePair<string, string>("client_id", _config.Value.ClientId) },
{ new KeyValuePair<string, string>("client_secret", _config.Value.ClientSecret) },
{ new KeyValuePair<string, string>("grant_type", _config.Value.GrantType) }
};
var client = new HttpClient();
var response = await client.PostAsync(_config.Value.UrlToken, new FormUrlEncodedContent(nameValueCollection));
var tokenResponse = await response.Content.ReadAsStringAsync();
return tokenResponse;
}
}
Where the UrlToken (url of the service to get the token
services.AddScoped<ITokenService, TokenService>();
public async Task<IActionResult> Index()
{
var token = JsonConvert.DeserializeObject<BearerToken>(await _tokenService.GetTokenAsync());
ViewBag.Token = $"{token.token_type} {token.access_token}";
ViewBag.UrlApi = _config.Value.UrlApi;
return View();
}
where BeareToken is a class we have created. We include in the ViewBag the toke and URL of the GraphQL service (also in the appsettings.json)
public class BearerToken
{
public string token_type { get; set; }
public string access_token { get; set; }
public int expires_in { get; set; }
}
<script>
var urlApi = "@ViewBag.UrlApi";
var myToken = "@ViewBag.Token";
</script>
const myQuery1 = `{
paginaNotasPrensa {
bag {
contentItems {
bla bla bla
}
}
}
}`;
const url = urlApi;
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", myToken);
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: JSON.stringify({ query: myQuery1 })
};
fetch(url, requestOptions)
.then(function (response) {
return response.json();
})
.then(function (res) {
salaPrensa.drawNotasPrensa(res.data);
})
.catch(function (error) {
console.error('Unable to query api/graphql (POST).', error);
});
Hi,
Before telling you about my issue, I want to show my gratitude and appreciation for this product, which I have recently discovered, and what I have been able to see really pleased very much. Thank you very much!!!
And now the issue.
I am trying to create web pages from content obtained through requests to the GraphQL API. The CMS project is published on an IIS Server and I make successful requests to the API from Postman. However, when I try to fetch the API from JavaScript (hosted in the same server) I cannot get the content.
I have made serveral tests changing the JavaScript code with no success:
The browser console shows this:
Going to the Event Viewer the request to the CMS raises the following error:
Any help would be appreciated. Best regards.