Basic Authorization in header vs Username and password in body - c#

I am facing two different situations . First method i can send username and password in body as model . Second method is to use basic auth in Header . Both methods are working fine.
Both methods are used only for first call just to authenticate, and the api returns a jwt token.
First Method:
curl -X 'POST' \
'https://localhost:7122/api/Authentication/token' \
-H 'accept: text/plain' \
-H 'Content-Type: application/json' \
-d '{
"userName": "test",
"password": "test"
}'
Second Method:
curl -L -X POST 'https://localhost:7122/api/Authentication/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Authorization: Basic ZzI0N2NmbnlwYzV3cmszaHAwZnU2cTk3N2YzZzYxY2hnODV1NzJzZmJkb3c3LmFwcHMudml2YXBheW1lbnRzLmNvbTowYk9xOHRkMzhMQVF4b3ptaWVqUDYwUzdzQnJkVkQ=' \
--data-urlencode 'grant_type=client_credentials'
Are they rules for what should i use in jwt token?
What is good practice to use?

Just to ensure everyone's on the same page let me outline a typical JWT-authentication workflow here:
User calls an anonymous POST API (no authorization required), with a username and password. API then returns a JWT. That's your Login API at line 3.
All other API calls require authorization, and so the client sends that as Bearer [JWT]. The server then determines if the token is valid and if not returns 401.
As I understand the question, you're asking whether, for (1), it's better to send the u/p through the authorization header using the Basic Authentication protocol (base64 etc) or to just post it in plaintext in the body of the login request.
There are two drawbacks I can see with using the auth header-
Sometimes headers are logged along the way while request bodies rarely are. Grant you, I think it would be unusual (if not unforgivable) for a system to be logging auth headers, but it's possible. The base64 encoding of course provides no security.
I have had difficulty in the past with basic auth headers actually going through. I'll just refer you to this thread which explores some of the possible pitfalls.
Other than the possibe logging issue, I can't think of any inherent issues with using one vs. other though. FWIW, I see APIs all the time that use the plaintext body approach while I've never seen an API that has you log in using basic auth and then returns a JWT.
Hopefully it goes without saying that you MUST ensure your APIs are only accessible through HTTPS. Otherwise you're hosed no matter where you put the password.
That said, if you're designing this from scratch and have access to both ends of the system and they will always be in sync, I'd consider sending a hashed password, regardless whether you use the auth header or POST body. As long as your client and server agree on the hashing method and iteration count, that significantly lowers the impact of that data possibly leaking or being logged somewhere. This would require a little homegrown security work though.
As for your other question,
Are they rules for what should i use in jwt token? What is good practice to use?
Rules? No. Conventions, definitely. Ultimately it's whatever information the application needs to be able to trust the user and give them access. These will be in the form of "claims". There's lots of literature on this but the definitive authority would be the RFC.

Related

Dropbox API App Authentication with .NET SDK

I've got a server-hosted .NET app that will need to connect to a single Dropbox account (on a schedule) and just overwrite a file there. In looking at the Dropbox authentication types, it states the following:
App Authentication
This type only uses the app's own app key and secret, and doesn't identify a specific user or team. The app key and secret are transmitted in place of a username and password using "HTTP basic access authentication".
Examples:
When supplying the app key and secret for App Authentication, the app key and secret are given in place of the HTTP username and password, respectively. This can be done either as separate strings, as shown in the first two examples below, or as an base64-encoded Basic authorization string in the Authorization header, as in the third example below.
Example 1:
curl -X POST "https://api.dropbox.com/1/metadata/link" -u "<APP_KEY>:<APP_SECRET>" \
-d
link="https://www.dropbox.com/sh/748egu7925f0gesq/AAHi80RJyhJFfkupnAU0wXuva?dl=0"
Example 2:
curl -X POST "https://<APP_KEY>:<APP_SECRET>#api.dropbox.com/1/metadata/link" \
-d
link="https://www.dropbox.com/sh/748egu7925f0gesq/AAHi80RJyhJFfkupnAU0wXuva?dl=0"
Example 3:
curl -X POST "https://api.dropbox.com/1/metadata/link" \
--header "Authorization: Basic <base64(APP_KEY:APP_SECRET)>" \
-d "link=https://www.dropbox.com/sh/748egu7925f0gesq/AAHi80RJyhJFfkupnAU0wXuva?dl=0"
Great! So I know it can be done without the whole OAuth authentication flow.....However, I can't seem to figure out how to perform App Authentication via the Dropbox.NET SDK by just supplying the AppKey and AppSecret.
Anyone have a code example of how to perform Basic Auth rather than OAuth against Dropbox?

How to send Bearer Token to different Website without Query String in C#/ASP.NET?

SSO/Oauth issue that I'm hoping is either simple, inexperience (probably) or just impossible.
I have Website A and Website B. Website A is under my control, and we currently use OAuth/OWin for SSO. Things work as intended, I can successfully make authentication/bearer tokens, all that jazz. Initially, to allow Website A credentials to be used for Website B, I'd pass the bearer token as a QueryString in the URL. The website would create and get the nessicary bits and bobs to get the Bearer token and stick it in a . User clicks the link, token is there in the URL.
What I'd like to do is take that information out of the QueryString/URL.
I've been looking at Request and Responses, using combinations of HttpWebRequest, Headers.TryAddWithoutValidation(), using Ajax calls to try and call Website B, and I still can't seem to get the token information over, even when I try to just use a dummy Website.
From my research, it seems like the answer is "Encrypt and pass it in a query string" or put it in the Authorization Header. But every example I see, shows that going to a API for validation and not passing it to another website login page. Anyone know any examples? Is this even possible without some weird inbetween?
If you want to remove it from the URL, you'll need to POST the token to Website B from Website A. The location you post to will need to be a server side endpoint that is prepared to look for the token and do something with it. You cannot POST to to a client side HTML page without it being in the URL.

Using the Google API .NET client with an existing access token

The use-case is the following: a mobile app is authenticating a user with Google and at some point, we need to publish a user's video to his YouTube account; for practical reasons, the actual publication should be done by the back-end (large files that are already stored there).
As the user is already authenticated by the app, the app just sends the user's access token to the back-end. Now my struggle is to find how to use this access token with the .NET client... So far I've tried to create instances of UserCredential from that access token but that doesn't seem to work. Also we don't need all the token refresh logic provided by UserCredential as we know that the access token is valid at this point.
Any help would be greatly appreciated, thanks!
Technically speaking you could just forward the access token, then when you want to call the api you just add the access token to the header as a bearer token
curl --request POST \
'https://youtube.googleapis.com/youtube/v3/videos?key=[YOUR_API_KEY]' \
--header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{}' \
--compressed
This could be done with manually with .net using a Http client.
However if you want to use the Google .Net client library you could do something like this.
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
scopes,
userName,
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
However you will need to do a few things. First off you need to make your own implmentation of FileDataStore which would accept an access token passed to it. I have a few samples of custom datastores here That you can have a look at they may help.
The second issue is that the client id and client secrete that you pass to the Google .net client library will need to be the same one that was used to create the access token to begin with. I am not 100% sure if this will be an issue as you are not passing a refresh token so the client library wont need to refresh the access token it just needs to use it.
There are other ways to create dummy credentials object for use with the Client library but this is the one that i have used in the past.
I dont personally think its a good idea for you to be passing access tokens around between servers in this manner. You really should have the user authorize your app properly.

How to securely get access token from Marketo

Marketo Rest API exposes a GET call to oauth/token uri, which exposes clientId and clientSecret parameters to all internet hops between the 2 networks. Am I missing something or is there a way we can securely get an access token?
Marketo also has a POST method for this endpoint where you can send the clientId and clientSecret as x-www-form-urlencoded POST parameters
curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" -d 'client_id=MY_CLIENT_ID&client_secret=MY_CLIENT_SECRET&grant_type=client_credentials' "https://MY_MARKETO_URL/identity/oauth/token"
I actually got my facts wrong, basically this get call is https, and query parameters will be sent encrypted over the wire once it establishes a secure connection to the server. Only caveat I found is that a server admin can read the credentials in clear text if browsed server file system which is a low risk.

ASP.NET MVC API - Authentication with username, password and one other field

I have an ASP.NET API that uses basic authentication to authenticate user requests. A new design requirement means I now have to authenticate with 3 fields (not just the username and password).
What is the best way to approach this? I've tried inserting the third field into the body and reading it on request. This works, but it feels wrong. Is there a way in which the third field could be part of the authorization header?
EDIT
I added the third field to the username (delimited with '|'). A HTTP module decodes and splits the header upon arrival, thus allowing for 3 field request authentication. Simple solution.
You could put the third field into another header. Or use some sort of delimiter and concatenate your third field into the auth header.
You can't add anything else into the Header - you're only allowed username:password (Base64 encoded). You can add an additional header or include the data in request body.
Basic authentication isn't exactly practical - particularly for something like a JavaScript application running in a browser. You'll end up having to proxy the API on the server because you'd otherwise leak the credentials to anyone who knows how to open the browser dev tools.
I'd look at securing your API with a token based approach. E.g. JWT or OAuth.

Categories

Resources