Since we updated our project to Swift 2 and Alamofire to version 2.0 we observe the following behavior regarding base auth: When we send a request (no matter what kind of) with authentication set, the request is always sent without authentication header the first time. After the backend answers with status code 401, alamofire adds the authentication header and and resends the request once again. We send the request using the following snipped:
Alamofire.request(request).authenticate(user: Config.serviceAuthUser, password: Config.serviceAuthPassword)
Is there a way to force Alamofire to include the authentiation header in every request? We want to avoid this kind of auth challenge for every request to lower network and server traffic. We had one solution working for iOS8, where we added the auth header in the session config of the shared instance of Alamofires Manager as follows:
Alamofire.Manager.sharedInstance.session.configuration.HTTPAdditionalHeaders = authHeader
But with iOS9 this does not work anymore, since only a copy of the configuration object is returned and modified.
Is there another way to avaoid this auth challenge process and force Alamofire to include the auth header with every request?
Making two requests is how the underlying URL Loading System was designed by Apple. The Alamofire authenticate methods simply allow you to provide the credentials to supply to the challenge if it occurs.
If you want to provide the header directly, the use the headers parameter on the request method. Additionally, you could insert the user:password credentials directly into the URL.
Related
I have a backend service configured as a subdirectory behind a reverse proxy. The backend has its own auth scheme, and it relies on the authorization header being formatted as
Bearer <JWT Token>
in order to validate a session. Unfortunately, the backend reveals what it is to any curious eyes, and doesn't keep any record of auth attempts/failures to filter with, for example, fail2ban.
I would like to hide the backend behind basic auth, so the page details are only loaded for authorized users, and so that I can monitor auth attempts/failures across all my backends with a simplified fail2ban filter.
The problem I'm encountering, is that in order for the client's requests to reach the backend, once it's secured behind basic auth, the Authorization header needs to be formatted as
Basic <base64-encoded username:pass pair>
The moment the client sets this header, though, the backend is unreachable. The backend and the client also have quite a bit of back-and-forth communication, and from what I can tell <UserToken> is dynamically generated for each login session.
I've tried
proxy_set_header Authorization <A statically generated and set JWT Token for testing>
In the location block of the backend. However, at some point in the transactions that result between client and backend, the Authorization header goes from
Basic (with backend asking for credentials)-> Bearer (backend is authenticated and loads a few resources until...) -> Basic (backend is now logged out and reauthenticating causes an infinite loop)
Essentially, as soon as the Authentication header is reset by the client to authenticate with basic auth, presumably for the client's next request, the backend becomes inaccessible. I would like a way to dynamically maintain two Authorization headers with nginx, if such a configuration is possible, and set the header appropriately according to where in the chain between client, proxy, and backend the request occurs.
I've also tried to experiment a little bit with a mapping like:
map $http_authorization $origin_auth {
"Bearer" $http_authorization;
}
and then adding this directive inside the server block:
add_header my-header $origin_auth always;
Just to see if I could store the header for retrieval on one of the client's future requests, or something... scrolling through dev tools though, to examine the header fields, "my-header" never assumes the value of the backend's expected authorization header.
I don't have enough experience with either the http protocol, or nginx, to know if the thing I want to accomplish is even possible, and I haven't found much help in other posts. I have tried throwing about 3 dozen hours of my life at the problem though, without any luck. Any help would be very welcome and appreciated.
I'm not finding any RestClient method to update its options, what I need to do is for example disable FollowRedirects for certain requests.
How do I do the following but with v107?
client.FollowRedirects = false;
Background: maybe a separate issue but current problem is that RestSharp is not following a redirect URL to Okta from a Location header of a response, it goes to the main Client URL instead. That is why I've decided to disable redirects to try following the redirect manually.
Most if not all of the properties in RestClientOptions are used to configure the HttpMessageHandler instance wrapped by RestClient. As each RestClient instance wraps a single HttpClient (and its handler), those options cannot be changed. It works the same way as configuring HttpClient, where you cannot change the AllowAutoRedirects property of the handler once it's configured.
That's why the documentation suggests using a specifically configured RestClient instance per remote API. Normally, the API uses a single convention and configuration requirement.
I have seen that some authentication endpoints require redirects, but most of the time the RestClient instance used to get the authorization token is not the one used to access the API itself with the retrieved token. So, the solution would be to have a separate instance for that purpose. Normally, it's only used once to get the token, then you can dispose it and reuse the token.
I keep posting the authenticator example from the docs https://restsharp.dev/usage.html#authenticator
Concerning RestSharp not following redirects properly, it's not what RestSharp does as it doesn't compose or execute HTTP calls physically. It just wraps HttpClient.
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.
I am interested in the theory about properly securing and integrating Vue CLI app with any generic backend framework using JWT.
Let's get straight to the questions:
Is there something like a response Authorization header which the backend can use to set the token automatically in Axios? (I only found a guide to set it manually from the response body)
Does the browser create a new instance of an app if I refresh and/or reopen a tab? Does this mean that the whole app including custom Axios instance with Authorization header is destroyed and the new one needs to set it once again (from local storage)?
Is Axios with (manually) set Authorization header CSRF safe? The point here is that the header isn't browser provided, but rather app provided (only visible to custom Axios instance in the application), right? So an attacker simply cannot get to the token, right?
And so while he can still make a call, it won't get authorized, right?
Short answers:
No you would need to set the Authorization header manually when you get the tokens, jwt is implemented by the client and server, not the browser
If you store jwt in cookies, you don't have to bother about re-setting the authorization header when the page reloads
Only Cookie-based jwt is vulnerable to CSRF exploits
normally browser stores and adds authentication header automaticly after successfull authentication.
I have a XMLHttpRequest and added the authentication header for basic auth. No problem at all.
Then I try to send a second request to the same url that is basic http protected without adding manually the http request header to this request. Poorly it seems that the browser is not storing the authentication provided in request 1. My goal is to add the authentication handler transparently to every request that follows the first one (like a native browser do).
Any idea? Thanks.
Browser only storing authetication requested from user. So, if you send 1st request w/o authentication fields, browser will prompt user for auth this time, remember credentials and use it for next requests transparently.