I have simple post request to cloud endpoint
#ApiMethod(name = "insertEmployee", httpMethod = HttpMethod.POST)
public Employee insertEmployee(#Named("phoneNumber") Long phoneNumber,
#Named("emailId") String emailId) { ... }
which accepts request of form
POST http://localhost:8888/_ah/api/employeeendpoint/v1/employee/87900850/q%40m.com
Is there something wrong with API design or url is wrong?
i have used REST client from browser to query localhost as well as deployment.
Related
I'm trying to get azure AD authentication working between a Blazor WASM app, and another API that I have running locally but on a different port. I need both applications to use the Azure login, but I only want the user to have to log in once on the Blazor app which should then pass those credentials through to the API.
I've set up app registrations for both apps in the portal, created the redirect url, exposed the API with a scope and I can successfully log into the blazor app and see my name using #context.User.Identity.Name.
When it then tries to call the API though, I get a 401 error back and it doesn't hit any breakpoints in the API (presumably because there is no authentication being passed across in the http request).
My code in the Blazor app sets up a http client with the base address set to the API:
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddHttpClient("APIClient", client => client.BaseAddress = new Uri("https://localhost:11001"))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("APIClient"));
builder.Services.AddMsalAuthentication<RemoteAuthenticationState, CustomUserAccount>(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccessTokenScopes.Add("api://d3152e51-9f5e-4ff7-85f2-8df5df5e2b2e/MyAPI");
//options.UserOptions.RoleClaim = "appRole";
});
await builder.Build().RunAsync();
}
In my API, I just have the Authorise attribute set on the class, and eventually will need roles in there too:
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class CarController
Then, in my Blazor component, I then inject the http factory and try to make a request:
#inject IHttpClientFactory _factory
...
private async Task RetrieveCars()
{
var httpClient = _factory.CreateClient("APIClient");
HttpResponseMessage response = await httpClient.GetAsync("https://localhost:11001/api/cars");
var resp = await response.Content.ReadAsStringAsync();
cars = JsonSerializer.Deserialize<List<Car>>(resp);
}
but this returns the 401 error. I've also tried a few different variations like just injecting a http client (#inject HttpClient Http) but nothing seems to be adding my authorisation into the API calls. The options.UserOptions.RoleClaim is also commented out in the AddMsalAuthentication section as I wasn't sure if it was needed, but it doesn't work with or without it in there.
Can anyone explain what I'm doing wrong and what code I should be using?
Common causes.
Most cases ,we tend to forget to grant consent after giving API
permissions in the app registration portal,after exposing the api
which may lead to unauthorized error.
Other thing is when Audience doesn’t match the “aud” claim when we
track the token in jwt.io .Make sure ,Audience=clientId is configured
in the code in authentication scheme or Token validation parameters
by giving ValidAudiences.And also try with and without api:// prefix
in client id parameter.
Sometimes aud claim doesn’t match as we mistakenly send ID token
instead of Access tokens as access tokens are meant to call APIs .So
make sure you check mark both ID Token and access token in portal
while app registration.
While Enabling the authentication by injecting the [Authorize]
attribute to the Razor pages.Also add reference
Microsoft.AspNetCore.Authorization as(#using
Microsoft.AspNetCore.Authorization)
Please see the note in MS docs and some common-errors
If above are not the cases, please provide with additional error details and startup configurations or any link that you are following to investigate further.
I am currently using ABP and ocelot to build a api gateway for microservices. Everything works fine but now I want to use api gateway as a domain resolver. ABP's Domain Resolver works to resolve tenantid from different domains but i want ocelot to able to send the resolved tenant id to the downstream services(Include __tenant header in the headers of the request to the downstream service).
You can create a Middleware for adding ResolvedId to the request headers. So the ocelot will send the edited request to downstream with the tenantId.
Example:
public class MyMiddleware : IMiddleware, ITransientDependency
{
private readonly ICurrentTenant CurrentTenant;
public MyMiddleware(ICurrentTenant currentTenant)
{
CurrentTenant = currentTenant;
}
public Task InvokeAsync(HttpContext context, RequestDelegate next)
{
context.Request.Headers.Add("__tenant", CurrentTenant.Id.ToString());
return next(context);
}
}
As you see, the middleware manupilates the request, it's adding the CurrentTenantId to the request.
The CurrentTenant is found before by your "domain tenant resolver".
You can use this middleware between app.UseMultiTenancy() & app.UseOcelot()
...
app.UseMultiTenancy();
app.UseMiddleware<MyMiddleware>(); // it must be here, between them
app.UseOcelot();
...
I am trying to connect to Salesforce Apex using POST. Slack has this pluggin, Outgoing Webhook which sends to a URL a POST request.
I have already created an APEX class to handle the request,
#RestResource(urlMapping='/test/accounts/*')
global with sharing class REST_slackAccount {
#HttpGet
global static void doGet() {
System.debug('Connected');
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
//accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
System.debug('Connected');
}
}
I am getting nothing from Salesforce when i trigger the request from Slack. What am i doing wrong.
I have already created a remote site settings.
The URL i used in Slack to make the POST request is:
https://test.salesforce.com/services//test/accounts/
Thank you.
It looks like that controller is only handling GET requests but Slack is doing a POST.
Is it possibile to allow requests to a gae endpoint method only from a specific domain (e.g. www.myname.com) and refuse everything else?
I'm looking for something like an app authentication (I don't want a user login)
many thanks
You could try out the following approach:
Inject the HTTPServletRequest parameter into your APIMethod.
#ApiMethod(path = "resources/{id}")
public Resource get(#Named("id") int id, HttpServletRequest request) {
//Use the request parameter here...
}
From the request parameter above, use the following:
String host = request.getRemoteHost();
Keep in mind that the host value can be your client or proxy's host name.
I want to use GAE Open-ID Federated Authentication using Java Script (without Java Servlet) End Point.
Is it supported via Java Script (without Java Servlet) End Point?
If yes how could I use Open-ID Federated Authentication with Java Script end point API call?
I had tried User in endpoint API
#ApiMethod(
name = "signMe.signGoogleId",
httpMethod = "POST",
scopes = { "https://www.googleapis.com/auth/userinfo.profile" , "https://www.googleapis.com/auth/userinfo.email" }
)
public SignIn signInOpenId(User user)throws
OAuthRequestException, IOException
{
User is null always even after logging with Google\Yahoo User.
I had tried HttpServletRequest req in endpoint API.
#ApiMethod(
name = "SignMe.signOpenId",
httpMethod = HttpMethod.GET,
scopes = { "https://www.googleapis.com/auth/userinfo.profile" , "https://www.googleapis.com/auth/userinfo.email" }
)
public SignIn signInOpenId(HttpServletRequest req)
throws IOException
{
UserService userService = UserServiceFactory.getUserService();
User newUser = userService.getCurrentUser();
newUser is null always even after logging with Google\Yahoo User.
Thanks,
Deepak
You could always dump the cloud endpoints way of doing it and go with general API authentication.
https://developers.google.com/appengine/articles/openid#fa
As would be done for non Cloud Endpoints applications. The down side is you wouldn't get any client authorization abilities, so any client code hit your API.
Google Cloud Endpoints OAuth does not seem to support Open ID at this time.