Store secret key in Xamarin Forms - authentication

I try to understand how I can store secrets in a xamarin forms project.
I have a web api core as a backend and a xamarin forms app as a frontend.
I am trying to code facebook authentication with Xamarin.Auth and I need to pass secret key to my app..
My thinking:
Store in the frontend: I could create a config file and encrypt it but the decryption will be in my source code and by decompiling and reflexion the hacker could retrieve the decryption source code and decrypt the secret key.
2: Store in the backend: I could store the keys in the backend but by sniffing requests sent a hacker could retrieve my secret keys.
Then what is the solution? How can I do it?
Thanks,

You could store your secret using Xamarin.Essentials. For Android your secret will be stored in the Androids KeyStore and within the Keychain in the case of iOS. Even if you decide to go with an encrypted config file I would strongly recommend storing your keys and IV in the SecureStorage instead of hard coding it in your source code. It is extremely easy to use and, well, as secure as it gets on a mobile device.
try
{
// write secret
await SecureStorage.SetAsync("oauth_token", "secret-oauth-token-value");
// read secret
var token = await SecureStorage.GetAsync("oauth_token");
}
catch(Exception ex)
{
}

Related

securing stripe secret key with server side

I am just trying to understand how to securely store the stripe secret key.
For sure I should not have it hardcoded on the app.
I am seeing in most tutorials secret value is saved in the server. Then it's retrieved to make call. Can't this be just be simply intercepted?
To make a request like this. This need a secret to passed in. I am using the amplify graphql.
var response = await http.post(Uri.parse('https://api.stripe.com/v1/payment_intents'), body: body, headers: {
'Authorization': 'Bearer sk_test_51JtrW7EI6WXcFFnPxSxwCIm24D8Gjj3e6hzxch4009kFOsXo7',
'Content-Type': 'application/x-www-form-urlencoded'
});
I am seeing in most tutorials secret value is saved in the server. Then it's retrieved to make call.
Most Stripe tutorials show the client-side/webpage/mobile-apps fetching the publishable key from your server. That key is (by design) public.
That approach helps especially with mobile apps where you cannot dynamically update your publishable key, you need to go through a full App Store review to get a new version of your app out, but fetching it from your server allows you to easily update a publishable key if needed.

Authenticate Google API request token in Python

My locally hosted bot that's integrated with Google Hangouts API uses python's Tornado module to accept user input from Google and responds with an appropriate reply. This is the request handler on the bot server:
class incomingRequestHandler(tornado.web.RequestHandler):
def post(self):
recievedData = json.loads(self.request.body.decode('utf-8'))
responseData = generateResponse(recievedData)
self.write({ 'text' : responseData })
This works great. Now I want to authenticate the incoming requests to make sure they're only coming from Google Hangouts.
The request from Google does have an Authorization bearer token in it's header and I'm sure that's what needs to be used for verification. As such, based on this article I took the recommended measures like using id_token.verify_oauth2_token() or querying https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123 but neither solution seems to work.
Could someone point me in the right direction for this? Am I using the correct token even or is this the wrong method for verifying incoming requests?
This issue originated from me having no idea what a JWT was nor knowing that what I'd encountered was a JWT. Another symptom of trying to handle things yourself, I guess.
Anyway, the solution is simply to get the Google certificates from this link, use openssl to generate corresponding public keys and feed the key specified (by kid value) in the authentication token to the jwt.decode() method of python's jwt module.
Here's a snippet of the solution:
selectedKey = certs.get(jwtHeader.get('kid')) //certs is a dict containing the public keys from Google
checksum = jwt.decode(token, selectedKey, algorithms=["<value-of-alg>"], audience="<value-of-aud>", issuer="<value-of-iss>") //token is simply the authentication token as a string
Note the following bash command to be sued to convert Google's x509 certificates into pem format public keys:
openssl x509 -pubkey -noout -in key.pem
I don't think python has a very modular solution for the above yet. Do let me know if there is.

AWS Encryption in React Native

I am in the middle of developing an app in React Native. What I am going to do is to encrypt Token coming from the third party using AWS Encryption and send encrypted Token to the server using the HTTP POST method.
Given details for encryption are KeyID, Access Key, and Secret Key.
KeyID: ARN: arn:aws:kms:us-west-1:188480393...:key/8rda...
aws_access_key_id: AKIA...
aws_secret_access_key: 17qKv...
I've tested the encryption process using AWS Encryption SDK CLI and it worked well. But I am not sure how to get started encryption with the above details in React Native.
Could someone recommend me any good example?
Thanks
Have you taken a look at the aws-encryption-sdk-javascript browser example code?
The browser example produces lots of error for me, like there is no crypto module in react native, which causes it to crash with client-browser package.
You can use aws-kms sdk inside react-native app as it supports react-native. It will be very similar to how you use it in your backend.
import AWS from 'aws-sdk';
// Create a new KMS client
const kms = new AWS.KMS();
// Encrypted text to decrypt
const encryptedText = 'ENCRYPTED_TEXT';
// Decrypt the text
kms.decrypt({ CiphertextBlob: Buffer.from(encryptedText, 'base64') }, (err, data) => {
if (err) {
console.log(err);
} else {
console.log(data.Plaintext.toString('utf8'));
}
});
You can find more this here

Laravel 5, how to send API token to mobile app

I have a mobile app which will call a REST API written using Laravel(5.2) framework.
This article on Laravel API authentication mentions how to authenticate users making calls to such an API. The caller should send the correct api_token to the server in the request.
My question is what would be a good way to get the api token to the mobile app? I'm currently thinking of creating a rest api which will authenticate the user based on username and password sent in the request and send the api_token in the response if the user sends a valid username/password pair. Is this method correct/secure? What things should I consider additionally if I do use this method?
You must use one of this methods to have a secure API
JWT TOKEN https://github.com/tymondesigns/jwt-auth
OAUTH2 https://github.com/lucadegasperi/oauth2-server-laravel
With this methods you only send once username and password and you obtain a token that is valid for a time you can decide. But as bigger is the time, more insecure.
To solve this, there are a renew token methods. With a valid token, you can obtain another valid and refresh the old. In this way, the username and password are more protected because they are not sent in every request.
Is not a good idea have the same token for each user all the time, as you saw in the example you provide. It´s very insecure. If someone get this token, he always will can send request in your name. The tokens must have a lifetime.
to answer your question how to send API token to mobile app i will recommend you that your mobile apps get a valid token and after refresh it.
Something as this works great to get a token in your app:
if ( thereAreTokenStored() )
{
if (! theTokenStoredIsValid() )
{
$authentication = refreshToken();
}
}
else
{
$authentication = authenticate();
}
To know all this issues I recommend you this book: https://apisyouwonthate.com/ . I learnt a lot of the 'API WORLD' with this book. It will help you to know all you need to create an API in a professional way and will provide the necessary tools and packages to achieve it and save a lot of work. And you will love your API!!
Yes this approach is safe. Additionally you also need to secure your connection to server by using HTTPS with a SSL certificate.

OWIN/OAuth2 3rd party login: Authentication from Client App, Authorization from Web API

I am trying to create a Web API that allows the API's clients (native mobile apps) to login using a 3rd party cloud storage provider. I'm using the following general flow from Microsoft:
Here is what I am trying to achieve:
I am using the default ASP.NET Web API Visual Studio template with external authentication, along with the OWin.Security.Providers Nuget package for Dropbox login functionality, and the existing built-in login functionality for Google (Drive) and Microsoft (OneDrive).
The issue I'm having is that the built-in functionality all seems to do the authentication and authorization as part of one flow. For example, if I set up the following in Startup.Auth.cs:
DropboxAuthenticationOptions dropboxAuthOptions = new DropboxAuthenticationOptions
{
AppKey = _dropboxAppKey,
AppSecret = _dropboxAppSecret
};
app.UseDropboxAuthentication(dropboxAuthOptions);
... and navigate to this url from my web browser:
http://<api_base_url>/api/Account/ExternalLogin?provider=Dropbox&response_type=token&client_id=self&redirect_uri=<api_base_url>
I am successfully redirected to Dropbox to login:
https://www.dropbox.com/1/oauth2/authorize?response_type=code&client_id=<id>&redirect_uri=<redirect_uri>
... and then after I grant access, am redirected back to:
http://<api_base_url>/Help#access_token=<access_token>&token_type=bearer&expires_in=1209600
... as you can see the token is part of that, so could be extracted. The problem is that the client needs to be the one navigating to Dropbox and returning the authorization code back up to the Web API, and the Web API would send the authorization code back to the third party to get the token which would then be returned to the client... as shown in the diagram above. I need the ExternalLogin action in the AccountController to somehow retrieve the Dropbox url and return that to the client (it would just be a json response), but I don't see a way to retrieve that (it just returns a ChallengeResult, and the actual Dropbox url is buried somewhere). Also, I think I need a way to separately request the token from the third party based on the authorization code.
This post seems a little similar to what I am trying to do:
Registering Web API 2 external logins from multiple API clients with OWIN Identity
... but the solution there seems to require the client to be an MVC application, which is not necessarily the case for me. I want to keep this as simple as possible on the client side, follow the flow from my diagram above, but also not reinvent the wheel (reuse as much as possible of what already exists in the OWIN/OAuth2 implementation). Ideally I don't want the client to have to reference any of the OWIN/OAuth libraries since all I really need the client to do is access an external url provided by the API (Dropbox in my example), have the user input their credentials and give permission, and send the resulting authorization code back up to the api.
Conceptually this doesn't sound that hard but I have no idea how to implement it and still use as much of the existing OAuth code as possible. Please help!
To be clear, the sample I mentioned in the link you posted CAN be used with any OAuth2 client, using any supported flow (implicit, code or custom). When communicating with your own authorization server, you can of course use the implicit flow if you want to use JS or mobile apps: you just have to build an authorization request using response_type=token and extract the access token from the URI fragment on the JS side.
http://localhost:55985/connect/authorize?client_id=myClient&redirect_uri=http%3a%2f%2flocalhost%3a56854%2f&response_type=token
For reference, here's the sample: https://github.com/aspnet-security/AspNet.Security.OpenIdConnect.Server/tree/dev/samples/Mvc/Mvc.Server
In case you'd prefer a simpler approach (that would involve no custom OAuth2 authorization server), here's another option using the OAuth2 bearer authentication middleware and implementing a custom IAuthenticationTokenProvider to manually validate the opaque token issued by Dropbox. Unlike the mentioned sample (that acts like an authorization proxy server between Dropbox and the MVC client app), the JS app is directly registered with Dropbox.
You'll have to make a request against the Dropbox profile endpoint (https://api.dropbox.com/1/account/info) with the received token to validate it and build an adequate ClaimsIdentity instance for each request received by your API. Here's a sample (but please don't use it as-is, it hasn't been tested):
public sealed class DropboxAccessTokenProvider : AuthenticationTokenProvider {
public override async Task ReceiveAsync(AuthenticationTokenReceiveContext context) {
using (var client = new HttpClient()) {
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.dropbox.com/1/account/info");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.Token);
var response = await client.SendAsync(request);
if (response.StatusCode != HttpStatusCode.OK) {
return;
}
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
var identity = new ClaimsIdentity("Dropbox");
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, payload.Value<string>("uid")));
context.SetTicket(new AuthenticationTicket(identity, new AuthenticationProperties()));
}
}
}
You can easily plug it via the AccessTokenProvider property:
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions {
AccessTokenProvider = new DropboxAccessTokenProvider()
});
It has its own downsides: it requires caching to avoid flooding the Dropbox endpoint and is not the right way to go if you want to accept tokens issued by different providers (e.g Dropbox, Microsoft, Google, Facebook).
Not to mention that if offers a very low security level: since you can't verify the audience of the access token (i.e the party the token was issued to), you can't ensure that the access token was issued to a client application you fully trust, which allows any third party developer to use his own Dropbox tokens with your API without having to request user's consent.
This is - obviously - a major security concern and that's why you SHOULD prefer the approach used in the linked sample. You can read more about confused deputy attacks on this thread: https://stackoverflow.com/a/17439317/542757.
Good luck, and don't hesitate if you still need help.