Am using web api 1. For Get apis i can enter the url (servername:portno/api/Controllername/apiname/) in the browser address bar and call the api directly from browser and get the json output
This seems to be a security issue. How can I restrict this url hit?
But I can not be using any authentication or authorization in the web api as its handled from UI side (mobility)
There are multiple ways how to secure your Web API. And actually you don't need some "HTML UI" to do them.
You can have either HTML UI where your user will HTTP POST form and will exchange login/password to some token (session id, OAuth single sign-on token etc.).
You can HTTP POST form without user as well, just from your code. And result will be the same, credentials are exchanged to some tokens, which are included in each next requests in HTTP headers
You can programatically restrict access to your API from some IP adresses or services
Anyway all the ways are require to implement authentication and/or authorization techniques. And what you see in HTML UI is only top of the iceberg and can be done without user.
When you need to close HTTP requests from browser just check HTTP header with browser agent.
Either authentication or just special handler for browser agent HTTP header, you will require at least MessageHandlers for both.
Your URL to start deep dive into WebAPI authentication http://www.asp.net/web-api/overview/security
Related
I have a Power App and Power Automate solution integrated with Docusign using their REST API's.
My issue is that I have users log into Docusign from a link which when completed and authenticated, returns an https response (authorization code) on the redirect uri. I want to be able to 'capture' the authorization code within Power Automate.
I want to avoid using custom connectors as they seem unreliable when using Oauth2 authentication and the users access token has expired. My preference is to use the HTTP REST API steps in Power Automate instead.
With a redirect to https://localhost:3000/auth/docusign/callback, I get the following https response:
https://localhost:3000/auth/docusign/callback?code=eyJ0eXAiOiJNVCIsImFsZyI6IlJTMjU2Iiwia2lkIjoiNjgxODVmZjEtNGU1MS00Y2U5LWFmMWMtNjg5ODEyMjAzMzE3In0.AQoAAAABAAYABwAAlzFclSfZSAgAACO4o5Un2UgCAOid-3Oz8jJHsDvIUG5hRR8VAAEAAAAYAAEAAAAFAAAADQAkAAAAZjA5Y2U4NDQtM2U5Yy00NjEzLTkwNzctNGY5MmFhY2NjZTc4IgAkAAAAZjA5Y2U4NDQtM2U5Yy00NjEzLTkwNzctNGY5MmFhY2NjZTc4NwBBDjKOCdhvSaNUWiI7O-21MAAAkAfAlCfZSA.zrYv2gsNFPVWHZpoO7-_5o4Ika3DxQpbNqlPUHiOvYFVL5igRnbZHh2V7OmN0bff7Tf14QF3pWaBAATozpIgzgj21m3ZjLbhY5J42eR1msXmoXjbBggibGC_FqbprVCzjSCvjbvMlwgEwda7LApdSWwr49ON9KhdN84qWD9sacJJvdi3Oi1KInImlVB_2rTpCLFhMD98PBv6b074yTqLOfwV31QT-6si8xLtk3G2vtn2gFZigXQxIA18b6tC-BM3NOILV1zwZNa1pstxxG2W8jJByUQlAux3d1GuS4vnDu_nr54mXULV0vY7txLFRiJA5w_E7Nlu2dlaOa5_DmfpNg
I want to intercept the code=eyJ0e........ in my flow.
I have tried setting up an http request and using the unique endpoint, used that as a redirect endpoint to send it to a receiving HTTP request flow. Docusign did not like the http request URL as a redirect.
I have to think this is a very simple thing to do and probably has to do with how the redirect/callback is configured in Power Automate. There maybe third party solutions that can act as a redirect intermediary which I can then GET with an API call. All ideas appreciated.
Currently I have created a WebAPI Project using identity framework and I have setup tokens to be returned when authenticating with the API.
So now I am looking at creating a standalone MVC application that will allow the user to make calls to the WebAPI to get back end data.
The goal is to separate functionality so that other applications can also start interacting with back end data through web calls.
So the confusion now is how do I setup my MVC project so that I can use the Authorize attributes on controllers with the token received from the WebAPI. I think I need to enable bearer tokens in the ConfigureAuth method in Startup.Auth.cs. However will that be sufficient enough? Or do I also need to enable the cookie authentication?
MVC and Web Api are fundamentally different when it comes to authentication. With Web Api, the bearer token has to be set in the header of the request, but this is not an issue as all API requests are done programmatically by the client, i.e. there's human-intervention involved in setting up the client to authenticate the request properly.
MVC is a different beast in that the actions are accessed generally via a web browser, which will not automatically affix a bearer token to the request header. What it will do is pass cookies set by the server back to the server. That's why cookie auth is used most typically for MVC web applications.
What you should do is enable cookie auth for the MVC site and then set up your sign in action to authenticate via the Web Api. When you get back a valid auth from the Web Api, then you can manually sign in the user via the Identity API:
await SignInManager.SignInAsync(user);
There are SNS application with 2 servers. Web backend server and REST API server.
The web server allows user login/logout with username/password, and show user information
The REST API server provides APIs like /topics, /comments, it should be stateless without session
The REST API will serve other web applications
There are some potential solutions, but neither is security.
Base Auth, the browser hold the username/password
Token with expiry timestamp, the problem is user could stay on the page until token expires
So, is there a way to protect the REST API when calling it from AJAX?
If I have understood your problem correctly I may suggest you use the Token solution. In order to maintain security you may generate new token on every request (& send it to client in response), which should be used to make next request, and disable token if it is once used or has expired.
Sorry, I meant to mention it as a comment, but I don't have enough reputation.
I have a client-side application on domain client-domain.example and a server-side application on domain server-domain.example. There is an API on the server-side. The client-side application sends AJAX requests to the server-side application. I use token-based authentication, so the client-side application sends token in headers with each AJAX request, for example: "Authorization: Bearer {some token}". It works fine with AJAX requests, when I need to get or post some data.
But the server-side API also keeps files. For example images. The files are private, only authenticated users can get them. And I need to show this images on the client-side in <img> tag. I can't get them using <img src="http://server-domain.example/path/to/image"> because in this case browser will not send Authorization header to the server-side.
What is the adopted solution? How client applications load images from server-side API?
There are three methods to solve it, the best approach to solve it is using the signed URLs
1. signed URL (can be insecure)
The first method simply creates a route without authentication (anonymous access) with a signature hash parameter that indicates if the resource can be loaded or not.
<img src="http://server-domain.example/path/to/image?guid=f6fc84c9f21c24907d6bee6eec38cabab5fa9a7be8c4a7827fe9e56f2">
When the server receives the request it must validate the guid if the expiration time has not been reached and, of course, check if the guid has a valid signature.
This approach is used by several files/documents servers like Dropbox, S3, CDN providers, etc.
See the technique in some companies.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html#private-content-overview-choosing-duration
https://client.cdn77.example/support/knowledgebase/cdn-resource/how-do-i-set-up-signed-urls
SECURITY:
the guid can not be just UUID of the image/user, because this doesn't provide any protection.
the guid can not be the same token you use for authentication (for example, you can't use auth-JWT tokens), because the user can share the link - and the user will share his tokens (see also (2)).
as mentioned above: guid should have a server-side mechanism of validation (date/signature/...) and should not provide more permissions than "access to the requested file"
2 Query String with JWT (most probably a security breach)
The second method is to pass the token by querystring with the image URL.
This method is not recommendable because it exposes clearly the URL and many servers sometimes write and expose public logs of URL accessed. The bad notice is that the JWT exposed normally the user can get control a lot of features further the image load.
<img src="http://server-domain.example/path/to/image?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c">
When the server receives the request you must validate the token by querystring and response with the content.
SECURITY NOTES: worse than (1) - because now authentication info (JWT auth) is exposed in the URL and can be cached/logged by servers OR accessed by any server in the middle OR the user can simply share the "image link" with their colleagues.
But if JWT is NOT an access token, but a one-time token generated specifically for accessing that particular file in a form of JWT then it provides the same level of security as (1).
3. cookies
The third method creates an authenticated cookie to validate the access of the image.
This method is not recommendable because is out of API pattern (webapi/token based authentication in general).
When the server receives the request you need to validate if the validate cookie is valid.
SECURITY NOTES: if you can provide security for your cookies and XSS and CSRF — are not just letters for you then it is a solution. But keep in mind: cookies are sent by the browser automatically with each request. Much more information about possible threats and solutions: Where to store JWT in browser? How to protect against CSRF?
My solution to basically this exact same problem, based on Jeferson Tenorio's answer below (option 1), was to sign the URL to my API call with an encryption of the image and the user's JWT token, e.g. path/to/image?token=xxxx. In laravel this is easily accomplished with encrypt($your_object) and decrypt($token) (https://laravel.com/docs/5.7/encryption), and then I used the extracted token to verify the user had access to the file in question. But there are probably many other libraries capable of handling this.
I would be curious if there are any security concerns, but from my perspective the JWT is never exposed via plain text and the encryption relies on a secret key that malicious actors shouldn't have access to, so it seems like it should be fairly secure. My only real complaint is that the token is quite long using this method which does not make for presentable URLs.
I have a web application and API Server, the web application consumes API always via AJAX except in a couple of scenarios.
When I enable SSO for both, I face the well known problem - how to handle redirect in AJAX.
(A bit more details: Azure mandates that the user should login to AD only via its login page - so ideally when a webpage or an api endpoint is accessed, they should get redirected to the azure login page. Since HTTP302 redirect doesn't work well with XmlHTTP, user will not get redirected to the authentication page when API is accessed via AJAX)
I have a few options to solve this issue:
When the web application is authenticated redirect to a predefined api endpoint (eg: 'api/login') and that will take care of api authentication and once that is done, redirect it back to the web app. So the user will be redirected this way:
web -> azure login -> web -> api -> azure login (auto login) -> api ->
web
Load the api endpoint in an iframe (or an image) and wait for the load complete event
Authenticate only web application - Remove api from sso context and find some other of way to identify and validate the web request at API side (tokens, cookies)
Please help me to choose a right pattern.
AJAX follows redirects automatically:
How to prevent ajax requests to follow redirects using jQuery
Detecting a redirect in jQuery $.ajax?
You need to distinguish between the reply from the service and the login page, which you get after AJAX follows the redirect (but not with safari+cors!). For example, detection could be done by checking for a string inside of response body. When detected, just redirect user to the login page by document.location=<login-page-url>.
Another option would be to use a token inside of "Authorization" HTTP header instead of SSO for backend-service protection:
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/