Using dart-lang/gcloud to read and write files to Google Cloud Storage, is it possible to provide customer-supplied encryption keys?
The Dart gcloud library is built upon dart-lang/googleapis which itself is interfaces with the Cloud Storage REST API, but the HTTP client it uses is so abstracted that it's hard to tell how to set the headers necessary for custom encryption.
Currently there is no support for custom encryption keys in package:gcloud.
Though the Storage constructor accepts an http.Client. So you can supply your own client which adds the headers, something along the lines of:
import 'package:http/http.dart' as http;
import 'package:gcloud/storage.dart' as storage;
class ClientWithKeys extends http.client {
final String encryptionAlgorithm;
final String encryptionKey;
final String encryptionSHA256;
ClientWithKeys(this.encriptionAlgorithm,
this.encriptionKey,
this.encryptionSHA256);
Future<StreamedResponse> send(request) {
request.headers['x-goog-encryption-algorithm'] = encryptionAlgorithm;
request.headers['x-goog-encryption-key'] = encryptionKey;
request.headers['x-goog-encryption-key-sha256'] = encryptionSHA256;
return super.send(request);
}
}
code() {
final client = new ClientWithKeys('<algo>', '<key>', '<sha256>');
final api = new storage.Storage(client, '<project-id>');
...
client.close();
}
Related
I am trying to create real time event listeners for firebase real time data base. I am looking to use the official REST streaming api and use an sse package for Golang.
I am thinking of using this package and there is a Client type in the package that looks like this:
// Client handles an incoming server stream
type Client struct {
URL string
Connection *http.Client
Retry time.Time
subscribed map[chan *Event]chan bool
Headers map[string]string
EncodingBase64 bool
EventID string
disconnectcb ConnCallback
ResponseValidator ResponseValidator
ReconnectStrategy backoff.BackOff
ReconnectNotify backoff.Notify
mu sync.Mutex
}
and a new client function that looks like this:
// NewClient creates a new client
func NewClient(url string) *Client {
return &Client{
URL: url,
Connection: &http.Client{},
Headers: make(map[string]string),
subscribed: make(map[chan *Event]chan bool),
}
}
I am thinking about writing a NewClient() function that passes in the authentication for firebase from the service account json. Does anyone know how to do this and what information I would need to pass from the json to where in the request/headers?
I need to call an external API from my spring boot project.
The external API is using OAuth 2 security authentication using client_credentials.
I have the client id and secret key. Can RestTemplate be used?
Can you suggest how to pass the id and key as part of the API call? Any example?
You can use RestTemplate too but I would suggest that WebClient will be more better as it is reactive and asynchronous and RestTemplate may be depreciated for future use (maybe not too).
Please refer to https://www.baeldung.com/spring-webclient-oauth2
#Autowired
WebClient client;
public Mono<String> obtainSecuredResource() {
String encodedClientData =
Base64Utils.encodeToString("bael-client-id:bael-secret".getBytes());
Mono<String> resource = client.post()
.uri("localhost:8085/oauth/token")
.header("Authorization", "Basic " + encodedClientData)
.body(BodyInserters.fromFormData("grant_type", "client_credentials"))
.retrieve()
.bodyToMono(JsonNode.class)
.flatMap(tokenResponse -> {
String accessTokenValue = tokenResponse.get("access_token")
.textValue();
return client.get()
.uri("localhost:8084/retrieve-resource")
.headers(h -> h.setBearerAuth(accessTokenValue))
.retrieve()
.bodyToMono(String.class);
});
return resource.map(res ->
"Retrieved the resource using a manual approach: " + res);
}
I am working on an ASP.NET 5 app and I would like to use JWTs to secure certain endpoints in the application. For the time being we have decided that we (as opposed to a third party) will issue the JWTs, as all of our clients are 'owned' by the application, i.e. we have no 'external' clients. In the example, I have an endpoint which creates and returns a JWT using the jwt-dotnet library as follows (I appreciate that this is a basic example, with no expiration time and a single subject claim etc.):
...
// include a single subject claim (user id)
var claims = new Dictionary<string, object>() { { "sub", "1234" } };
var key = "EXAMPLE_SECRET_KEY_TO_SIGN_JWT";
var token = JWT.JsonWebToken.Encode(claims, key, JWT.JwtHashAlgorithm.HS256);
...
// return JWT
I can encode, and decode this JWT using the same key as one would expect. In my Startup.cs file, I am using Microsoft.AspNet.Authentication.OAuthBearer middleware to Authorize the relevant routes in my controllers which have the [Authorize] attribute specified. However, after looking at a number of posts including here and here I cannot seem to find an example of how to supply this signing key to the OAuth middleware in the same fashion. The code in my Startup.cs file looks as follows:
public class Startup
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseErrorPage();
app.UseOAuthBearerAuthentication();
app.UseMvc();
}
...
public void ConfigureServices(IServiceCollection services)
{
services.Configure<OAuthBearerAuthenticationOptions>(bearer =>
{
bearer.AutomaticAuthentication = true;
bearer.TokenValidationParameters.ValidAudience = "Example audience";
bearer.TokenValidationParameters.ValidIssuer = "Example issuer";
bearer.TokenValidationParameters.ValidateAudience = true;
bearer.TokenValidationParameters.ValidateIssuer = true;
bearer.TokenValidationParameters... // how do I set the signing key as a string literal?
});
services.AddMvc();
}
}
My assumption has been that I should be able to simply supply the same string literal key to the middleware so it can validate the token signature. However this does not seem to be the case, as the examples discuss using RSA keys or certificates as opposed to providing a single key/string literal.
I appreciate that I may be missing something here, or indeed that this may be the wrong approach and I should't be able to do this!
EDIT: symmetric keys are now natively supported in the RC2 nightly builds:
var key = Convert.FromBase64String("base64-encoded symmetric key");
app.UseJwtBearerAuthentication(options => {
options.AutomaticAuthenticate = true;
options.AutomaticChallenge = true;
options.Authority = Configuration["jwt:authority"];
options.Audience = Configuration["jwt:audience"];
options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(key);
});
You can't, at least not without a bit of plumbing: the OAuth2 bearer middleware relies on IdentityModel 5, that doesn't support symmetric keys like the one you're using in your first snippet.
Of course, symmetric keys will be eventually supported (https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/250), but in the meantime, using an asymmetric key (like a RSA key) is recommended.
You can also implement symmetric keys support yourself (see https://gist.github.com/sandorfr/4039d540b6b552154522), but using a RSA key is definitely a better option.
So a UserManager has a function called GenerateUserTokenAsync(string purpose, TKey userId).
What does this do in ASP Identity? Can I use this to generate OAuth Bearer tokens? Also what is the purpose parameter for? What values can this be?
UserManager.GenerateUserTokenAsync(User, TokenProvider, Purpose)
can be used to generate Tokens for purposes that are not implemented be the UserManager.
One example could be an invitation system. In a WebProject you need to create a TokenProvider like this:
public class InvitationTokenProvider<TUser> : DataProtectorTokenProvider<TUser> where TUser : class
{
public InvitationTokenProvider(IDataProtectionProvider dataProtectionProvider, IOptions<InvitationTokenProviderOptions> options, ILogger<DataProtectorTokenProvider<TUser>> logger) : base(dataProtectionProvider, options, logger)
{
}
}
and the InvitationTokenProviderOptions
public class InvitationTokenProviderOptions : DataProtectionTokenProviderOptions
{
}
then you can register it in StartUp.ConfigureServices().
services.AddIdentity<User, Role>(options =>
{
// ...
}).AddEntityFrameworkStores<ApplicationDbContect>()
.AddDefaultTokenProviders()
.AddTokenProvider<InvitationTokenProvider<User>>("Invitation");
Afterwards you can use it with the UserManger like this
// create a token
string token = await _userManager.GenerateUserTokenAsync(user, "Invitation", "Invitation");
// verify it
bool result = await _userManager.VerifyUserTokenAsync(user, "Invitation", "Invitation", token);
If you are going to use the token in URLs, don't forget to make it URL-Safe (it may contain '/' and other symbols.
Also check if trailing '==' is lost on the way through emails and browsers.
Documentation for 'GenerateUserTokenAsync' says
Get a user token for a specific purpose
This method should not be used directly, (no idea why it is public). It is used in generating password reset token (GeneratePasswordResetTokenAsync) and email confirmation tokens (GenerateEmailConfirmationTokenAsync). And it is used like this:
GenerateUserTokenAsync("Confirmation", userId); // email confirmation
GenerateUserTokenAsync("ResetPassword", userId); // password reset
In default implementation of token provider (TotpSecurityStampBasedTokenProvider) purpose is used as some sort of password in cryptographic token generation.
Overall, you don't need to use GenerateUserTokenAsync, just call GeneratePasswordResetTokenAsync or GenerateEmailConfirmationTokenAsync.
I am writing a test application for Microsoft CryptoAPI. I want to export the secret key of one party using the public key of the second party, and then import that secret key as the second party's secret key (this sets up a shared secret key for communication). Here is my code:
if(!CryptExportKey(encryptT->hSymKey, decryptT->hPubKey, SIMPLEBLOB, 0, keyExBuf, &bufLen)) {
FormattedDebugPrint(NULL, GetLastError(), "could not export secret key", TRUE);
return -1;
}
if(!CryptImportKey(decryptT->hCryptProv, keyExBuf, bufLen, decryptT->hPubKey, 0, &(decryptT->hSymKey))) {
FormattedDebugPrint(NULL, GetLastError(), "could not import secret key", TRUE);
return -1;
}
And this gives the error:
80090001: Bad UID.
The public keypair is being generated for both encryptT and decryptT (sender, receiver) by calling:
CryptGenKey(encryptT->hCryptProv, CALG_RSA_KEYX, CRYPT_EXPORTABLE, &(encryptT->hPubKey))
Any idea what could be causing the error?
Thanks,
Never mind, I figured it out. Basically, you can't just use another public key directly even if it's initialized the same way -- I needed to first export that public key, and then import it using the handle to the cryptographic provider of the other party.