Google books public api - 401 - javascript

When locally trying to use Google books api to get public data:
Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."
API_URL = "https://www.googleapis.com/books/v1/volumes";
this.http
.get<GoogleBooksApiInterface>(`${this.API_URL}?q=${title}`)
Even after adding &key=api_key, the response is the same.

After spent some time to figure it out and found solution (which is not unfortunately mentioned in google documentation):
to make it works in my case I use NodeJS on the backend side and moved there this API request.
Angular => NodeJS => API call => Angular

Related

ASP.NET Web API microservices + Angular front end - how to manage auth cookie?

Can anyone suggest what are the standard practices when it comes to Cookie Authentication (ASP.NET) and a separate (CORS) front-end using Angular.
The problem that I have is when I log in in my Web API using Postman/ Swagger - the Auth Cookie gets created. When I use Angular through localhost:4200, no cookie is created.
For angular post method Http headers configuration I use {withCredentials: true}
and these are my configurations for the cookie plus CORS for the API:
1 - Middleware
app.UseCors(builder =>
builder
.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowCredentials()
.AllowAnyMethod());
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers()
.RequireCors(MyAllowSpecificOrigins);
});
app.MapControllers();
app.Run();
2 - registering the CORS services:
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("http://localhost:4200");
policy.AllowAnyHeader();
policy.AllowAnyMethod();
policy.AllowCredentials();
});
});
3 - Cookie configuration:
builder.Services.ConfigureApplicationCookie(config =>
{
config.Cookie.Name = "Identity.Cookie";
config.LoginPath = "/User/Login";
config.LogoutPath = "/User/Logout";
config.Cookie.HttpOnly = false;
config.Cookie.SameSite = SameSiteMode.None;
config.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
Some users reported that no cookie should be created in the client browser when using Localhost:4200, for example I've read this opinion but cannot understand what it means, exactly:
"Subsequent requests will be sent by the browser and the browser will automatically bring the cookies."
Maybe, I should only assign a simple variable which checks if the response of the login is 200 Okay and then use it as a confirmation, later in the code?
So, can anyone advise what is the standard practice, to authenticate my front-end?
Okay, so I updated my Cookie and CORS configuration.
Also, currently, my Angular Front End is using http, but in future versions I shall fix it with https.
So for now, I can confirm that this configuration is working.
Whenever I login from my Angular Application successfully - a cookie is created in it. This cookie then is also successfully read by the backend, thus completing the security process, required by the backend!
I hope I helped someone reading this topic. And don't forget to add
{withCredentials : true}
in the headers of each HttpRequest made from your Angular application.

Wrong audience for JWT using ADAL.js

I'm using the adal-angular library (but not with Angular) in my SPA to try to acquire an access token that I can use to call the SharePoint APIs (https://<my-tenant>.sharepoint.com/_api/).
I've registered an application in Azure AD and enabled the implicit flow in the manifest, and I'm now running my SPA locally, which is why there's a localhost redirect URI. The code below is being executed on startup:
const context = new AuthenticationContext({
clientId: '<my-client-id>',
redirectUri: 'http://localhost:3000/signin',
popUp: true,
loginResource: 'https://<my-tenant>.sharepoint.com',
callback: () => window.location.reload()
});
const user = context.getCachedUser();
if (!user) {
context.login();
} else {
context.acquireToken('https://<my-tenant>.sharepoint.com', (error, token) => {
console.log(error, token);
});
}
I'm already logged into the SharePoint site, so with this config everything happens automatically and I see a JWT access token logged to the console. However, when I inspect the token, I see that the audience is <my-client-id>. When making a call to https://<my-tenant>.sharepoint.com/_api/v1.0/me using the access token, I then get a 401 response with the following error message:
{"error_description": "Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}
I'm pretty sure this all boils down to me not understanding the OAuth2 flow properly, but... how can I acquire a token that SharePoint can actually be used with SharePoint? Am I thinking about this the wrong way? It kinda defeats the purpose if the token retrieved by my app can only be used to authenticate against my own app.
Getting an access token to SharePoint is well described here:
OneDrive for Business authentication and sign in
You should consider first getting a token to the Discovery Endpoint:
Using an access token received for resource
https://api.office.com/discovery/ you can make a request to the
discovery API to learn which services are available
If the call is successful, the response body contains JSON data with
information about the services available for the user and your app.
{
"#odata.context": "https:\/\/api.office.com\/discovery\/v1.0\/me\/$metadata#allServices",
"value": [
{
"#odata.type": "#Microsoft.DiscoveryServices.ServiceInfo",
"capability": "MyFiles",
"serviceApiVersion": "v2.0",
"serviceEndpointUri": "https:\/\/contoso-my.sharepoint.com\/_api\/v2.0",
"serviceResourceId": "https:\/\/contoso-my.sharepoint.com\/"
}
]
}
There you should get your valid Resource ID... but the issue here may just be that you did not include a forwardslash (/) at the end of the Resource URL in your sample code.

Unauthorized request handling in Angular.js with Box API v2

I am developing a web app with angular.js v1.5.7, which integrates Box Services using oauth2 authentication on the client-side to retrive the tokens for accessing the API.
I have a problem when the access token expires. I make a request with the expired token, and I receive a 401 (unauthorized) response that I can't catch in Angular because the response has a status code of -1. This happens before I am able to catch this response in a $httpsInterceptor.
I made a repository in GitHub to demonstrate this behavior https://github.com/danyfu/box-api-test, it's an express server that serves the 3000 port the Angular app.
In the Angular app, it's only a button you click to request to the API to GET the root folder of the user:
https://api.box.com/2.0/folders/0?fields=id,name,type,item_status,size,item_collection,shared_link
With the request I add the access token.
When I make the request with the invalid token, the response returns two error logs.
Errors
When I make the request with a valid access token, it retrieves the folder info and a status of 200.
Correct Information
You can use passport-box which will do the oauth flow in your app.
https://github.com/bluedge/passport-box
Here's an example where I use it as well:
https://github.com/kendomen/boxadmin

Get all user photos from instagram

I'm working on some test app, that uses auth0 and IONIC. I have established connection with auth0, and now i want to get user data by this code:
$http({
method: 'GET',
url: 'https://api.instagram.com/v1/users/self/?access_token='+store.get('accessToken')
}).then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
console.log(response);
});
I get 400 Access-Control-Allow-Origin error. Can anybody tell me what to do? I can't find anythink on internet that'll help me...
Disclosure: I work for Auth0
The AccessToken returned at the end of Auth0 Login flow is an access token valid for calling Auth0's API's and not Instagrams. In order to do this you will need the Identity Provider's access token in this case that is Instagram.
The complete flow will look like the following
User Logs in from Instagram
Your IONIC app makes a call to your server
Your server fetches the IdP Access Tokens from Auth0 using either a non-interactive client flow or using management api v2
Your server makes the call to Instagram
You can do this via a webtask the following example highlights the flow to fetch the IdP Access Token via Management API v2 https://github.com/vikasjayaram/ext-idp-api-webtask
I am suggesting the flow because Starting Aug 16 2016 these tokens will not be sent back in profile.identities array the as they are so far.

Using IdentityServer3 with Single Page App (UseIdentityServerBearerTokenAuthentication)

Background
I'm using these technologies to secure a WebApi application:
ThinkTecture.IdentityServer3
OWIN (Azure)
Single page app - javascript client
Refer to the Simple OAuth2 Walkthrough sample (github)
In the sample above the .NET console app client requests a token from IdentityServer and uses it to access the WebApi application. This works fine in the sample.
I want to change the .NET console app Client to a javascript single page app Client. I have tried adding a proxy login controller that does the request to IdentityServer on behalf of the javsacript Client and returns the token back to the client in a cookie.
Code
[HttpPost]
[Route("login")]
public HttpResponseMessage Login(LoginRequest request) // Proxy to IdentityServer3
{
var tokenClient = new TokenClient(
"https://localhost:44333/connect/token",
"javascript client",
"client secret");
var tokenResponse = _tokenClient.RequestResourceOwnerPasswordAsync(request.username, request.password, "api1").Result;
var cookie = new CookieHeaderValue("access_token", tokenResponse.AccessToken);
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = "localhost";
cookie.Path = "/";
var response = new HttpResponseMessage();
response.Headers.AddCookies(new CookieHeaderValue[] { cookie });
return response;
}
I get the access token back successfully in the javascript client, however the API doesn't recognise it.
Question
How should I pass the a token generated by IdentityServer to the javascript application, and how do I use it to access the WebApi?
Let's say your token end point is "https://localhost:44333/connect/token" (as you have mentioned). Hitting that endpoint with a POST request with a body like the following will return a token:
grant_type=password&client_id=youtclientid&client_secret=yourclientsecret&username=yourUserName&password=YourPassword&scope=list_of_requested_scopes
You use a JS variable to store your token, and then in order to use that token to access protected APIs, you have to send it as part of the header in the request, similar to the following: In your request's header, you will have:
Authorization: Bearer eyJ0eXAiOiJKV...
where "eyJ0eXAiOiJKV..." is the token you received in the first step.
Using oidc-client.js or creating something similar on those lines as the size of this js library is large.
Check this link out.
https://github.com/IdentityModel/oidc-client-js/tree/master/sample
and the video
https://vimeo.com/131636653
We are using the IdentityServer infrastructure to get to initial login and then the token(s) id/access for all further communications.

Categories