Passport basic authentication only for API requests - express

I'm writing an express/node/angular application. When the client-side angular controllers need some data, they request it from the server using an endpoint that returns JSON.
This endpoint is behind some passport.authenticate('local') middleware, however this endpoint is exactly what we need for a public API.
Our API uses a passport.authenticate('basic') (basic http auth).
I'm trying to find a way to use the same URL for both, but I don't want users to my site who aren't logged in to see an http authentication window. I somehow need to tell "is this an API request, or an xhr request from the site"
For example, I want the following URL to work for a locally-authenticated user (would have been authenticated via a /login route) or for an API user:
app.get('/api/v1/tasks', passport.authenticate('basic'), tasks.list);
The only alternative I know of that works is splitting these into two different URLs, one for the site to use internally, and one for the public API. Maybe that's a better strategy for security/organization anyway?

Related

Login user via GET (basic auth header) or POST

I've been doing some HTTP methods and header research recently if we should use GET with basic authorization instead of POST when submitting?
HTTP Methods
The GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
The POST method submits an entity to the specified resource, often causing a change in state or side effects on the server.
As we see here, the POST method normally changes the state of the server. If sending out JWTs/HTTP cookies, we are not modifying the state of the server. Nor are we creating a new resource in the server.
I understand that we should not not send the username and password as a GET parameter but should we use the authorization header instead?
Basic authentication
For "Basic" authentication the credentials are constructed by first combining the username and the password with a colon (aladdin:opensesame), and then by encoding the resulting string in base64 (YWxhZGRpbjpvcGVuc2VzYW1l).
Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
The only advantage I see to using POST over GET is that we need no extra code in the HTML/JS on the client side to send headers via the fetch API. To send headers, we would need an onsubmit and then check if status code is 200. If 200, we will need to redirect to the page after the login screen. Then again, if using the fetch API, this means the server does not need to send a new HTML page to the client all the time either.
Should we use GET with basic auth or POST when logging in since we don't create a resource/modify the server state?
Would this change if say we enable 2FA since we would need to generate a code for that user?
Doing basic authentication in the browser and using GET is not that recommended.
To do your own login form it is better to always do it using HTTPS and POST. Do post the username/password in the body of the request and secure it with proper CSRF protection.
If you want to level up, you can always look at the OpenIDConnect approach, but that is more advanced depending on your needs.
Also, a good approach is to explore how existing site implement a login form and look at the HTTP(s) traffic in a tool like Fiddler.

How to use the eBay Browse API just to search for products via one server

I try to migrate from eBay Finding API to Browse API. My technical setting is quiet easy:
A Server searches the Browse API to find products by a keyword. Thats it.
Does anybody know if I need to implement OAuth, a redirection page for eBay-Users to log in etc.? I don't need all those features..
Thanks!
You can use the browse API with the client credential flow that mints the Application access token.
Application tokens are general-use tokens that give access to interfaces that return application data. For example, many GET requests require only an Application token for authorization.
See Documentation
The client credential flow does not require a User to Login via eBay and the redirect etc. However, you can only use the "GET" methods like getItem, getItemByLegacyId or search for example.
If you using NodeJs or Browser you can checkout the "Get Item" example here. (The library will get the Application access token automatically and return the result.)

ASP.NET Core API Securing PDF File Endpoint

I have an endpoint on my API that serves PDFs to users, and a web app that displays a link to the endpoint in a simple href to allow the user to click on the link and have the PDF download and display directly in their browser. A sample link to an endpoint would look like:
<a href=http://localhost:51660/api/v1/MyAPI/GetPDF?id=94a8ea0b-aec9-4812-839f-a2f7f4d0e122>
This works just fine, the problem is this endpoint is difficult to secure as I can't really pass the JWT token in the headers as we would for the other endpoints in the API since it's just a simple link in order to use the native PDF viewer in browsers. I can try storing a cookie from the front end with the JWT token then try to read this from the API, though this feels like a clunky solution to add in cookie authentication and use this for a singular route in the API, when everything else uses JWT bearer authentication but I can't think of any other way around this.
I need to be able to pass the token so that I can verify the user and the organisation they are a part of to ensure they aren't trying to access a file they shouldn't be allowed to view, but I can't really think of a non-clunky way to get around this. Is this something I'll just have to accept?

Accessing the `student_view_url` via Open Edx API authentication or alternatives?

I’m working on a React Native application where all the Edx course information needs to be displayed offline.
I’ve authenticated the app using oauth2 endpoint (client_id=…&grant_type=password&username=user#example.com&password=p455w0rd to {{root}}/oauth2/access_token/) and can access the API endpoints to get the users enrolled courses ({{root}}/api/enrollment/v1/enrollment) and the blocks within those courses ({{root}}/api/courses/v1/blocks/?course_id={{course_id_url_friendly}}&depth=all&nav_depth=3&return_type=list&username={{username}}). What I’m struggling to get is the contents of the HTML blocks.
I see in the official app (when viewing requests via a proxy) that it will request the actual webpage of the course, presumably the student_view_url.
Is this the only way to get that content or is there an API endpoint I can use to return the content?
If the only way is to request the rendered student_view_url, how do I access that page? The only way I can tell in the official app is it looks like it’s passing the cookies to authenticate with the studen_view_url, which it must get when it authorises the user via the oauth2 endpoint. The cookies I get don’t work though, which I’ve tested in Postman (if I use cookies that I got from browsing my Edx site in Chrome, they do work). This begs me the question, is my authentication correct as I don’t get any scope returned when the official app returns a scope filled in with read write and two others.
A sample of what my authentication returns:
{
"access_token": "a12345...",
"token_type": "Bearer",
"expires_in": 2591999,
"scope": ""
}
To reiterate;
Is there a way to request the HTML content via the API (so returned in a JSON request) rather than the student_view_url
If not then how do I authenticate to access the student_view_url?
So I worked out how to do point 2.
Before requesting any HTML content you need to hit the endpoint {{root}}/oauth2/login/ with the auth token that you provide to other endpoints. This will pass back a usable sessionid cookie that will let you access content that's not public (so long as the user has access).
As an aside, to pass the cookie through fetch() requests, I had to pass the option credentials: 'include'.

ASP.NET MVC DotNetOpenAuth authorization server how-to

I have this scenario: a corporate site (MVC 4) and a web shop; add OAuth 2 SSO functionality. Both sites have their own members, but the corp site (for which I'm responsible) must also work as an OAuth 2 authorization server and will store a web shop user id for each member. The shop requested the following endpoints:
Auth endpoint
• authorization:
…/oauth2/authorize?client_id={CLIENT_ID}&state={STATE}&response_type=code&redirect_uri={REDIRECT_URI}
• token
…/oauth2/token?code={TOKEN}&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&redirect_uri={REDIRECT_URI}&grant_type=authorization_code
…/oauth2/token?refresh_token={TOKEN}&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&redirect_uri={REDIRECT_URI}&grant_type=refresh_token
API endpoint
• getid (will return JSON with the shop id of the member):
…/oauth2/api/getid?access_token={TOKEN}
I don't have experience with OAuth, so I was looking at the DotNetOpenAuth samples and have concluded that I need to implement an OAuthAuthorizationServer, but modifying the sample to fit my requirements is difficult as it seems to do more and is complex.
As researching DotNetOpenAuth seems to be so time consuming, I'd like to ask: is modifying the OAuthAuthorizationServer sample the right approach? Or should I try to make a native implementation or try a different OAuth library that may be easier to use in my situation?
Please comment on my overall plan:
-keep the corp site member login flow standard forms auth, straightforward LogOn controller
-add an OAuth controller that will implement the three required endpoints as actions
-when the authorization action is reached, I validate the client and redirect to LogOn passing on the redirect_uri; I think the Authorize ActionResult from OAuthController.cs from the sample is where I should start investigating this, and return an AccountAuthorizeModel. Is this correct?
-after the user logs in, and if the login page was reached from the authorization endpoint, I redirect to redirect_uri with the code attached; I don't know where to start with this one. PrepareApproveAuthorizationRequest then PrepareResponse? Where does the code come from? Where in the flow should I add a new ClientAuthorization in the database?
-the shop will then use the code to get or refresh the token, from the /token endpoint; simply return HandleTokenRequest?
-with the token the shop site will be able to get the member data JSON; have to find out how to validate the token
Now, besides adding a Clients table to store the client ids and secrets, and ClientAuthorization to keep track of who's authorized, I don't know if the other tables from the DotNetOpenAuth sample are used and when: Nonce, SymmetricCryptoKey, User.
Modifying OAuth2AuthorizationServer.cs seems straightforward, I only have to add real certificates and make sure the clients are pulled from my data context.
Thanks!
I think you are right in most of the points. Let's comment them:
OAuth server should have 2 endpoints (not 3), as requesting token and refreshing token goes to the same endpoint (TokenEndpoint).
It depends if your are going to implement a different authentication server (or controller), or you are going to implement the authentication responsibility inside the authorization server. In case they are separated, the authentication server should be the one responsible of displaying the logon, authenticate and communicate with authorization server using OpenID protocol (Also supported by DotNetOpenAuth).
Once the user is authenticated, the authorization server should store the data of the user identity somehow, and return the authorization code (if using this Oauth flow) using DotNetOpenAuth functions:
var response =
this.AuthServer.PrepareApproveAuthorizationRequest(AuthorizationRequest,
User.Identity.Name);
return this.AuthServer.Channel.PrepareResponse(response);
finalResponse.AsActionResult();
I don't think you need to save nothing about the authorization process in the database, and the code is generated by DotNetOpenAuth and sent to the client into the query string of the redirection.
Then, the client should get the code (ProcessUserAuthorization) and call the TokenEndpoint. This endpoint is just returning HandleTokenRequest, that internally is calling to some OAuthAuthorizationServer functions, such as CreateAccessToken.
Once the client has the access token, it should call the resources, sending the token into the HTTP Header 'Authorization'. The resource server is the responsible to validate the token.
var resourceServer = new ResourceServer(new
StandardAccessTokenAnalyzer(signing, encrypting));
AccessToken token = resourceServer.GetAccessToken(request, scopes);
A store provider for nonce and crytoKeys is needed using this flow. Have a look to class InMemoryCryptoKeyStore in:
https://github.com/DotNetOpenAuth/DotNetOpenAuth/wiki/Security-scenarios
Hope this helps!