Keycloak check permissions via Authzclient - java

i'm trying to check user permissions from a keycloak server via the keycloak authzclient. But failing constantly, by now i'm not sure if i have some misconceptions about the process.
AuthzClient authzClient = AuthzClient.create();
String eat = authzClient.obtainAccessToken("tim", "test123").getToken();
AuthorizationResource resource = authzClient.authorization(eat);
PermissionRequest request = new PermissionRequest();
request.setResourceSetName("testresource");
String ticket = authzClient.protection().permission().forResource(request).getTicket();
AuthorizationResponse authResponse = resource.authorize(new AuthorizationRequest(ticket));
System.out.println(authResponse.getRpt());
The last call authResponse.getRpt() fails with a 403 forbidden.
But the following settings in the admin console evaluates to Permit?
keycloak evaluation setting
The Client config is:
{
"realm": "testrealm",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "tv",
"credentials": {
"secret": "d0c436f7-ed19-483f-ac84-e3b73b6354f0"
},
"use-resource-role-mappings": true
}
The following code:
AuthzClient authzClient = AuthzClient.create();
String eat = authzClient.obtainAccessToken("tim", "test123").getToken();
EntitlementResponse response = authzClient.entitlement(eat).getAll("tv");
String rpt = response.getRpt();
TokenIntrospectionResponse requestingPartyToken = authzClient.protection().introspectRequestingPartyToken(rpt);
if (requestingPartyToken.getActive()) {
for (Permission granted : requestingPartyToken.getPermissions()) {
System.out.println(granted.getResourceSetId()+" "+granted.getResourceSetName()+" "+granted.getScopes());
}
}
Just gives me the "default resource"
7d0f10d6-6f65-4866-816b-3dc5772fc465 Default Resource []
But even when i put this Default Resource in the first code snippet
...
PermissionRequest request = new PermissionRequest();
request.setResourceSetName("Default Resource");
...
it fives me a 403 . Where am I wrong?
Kind regards
Keycloak Server is 3.2.1.Final.
keycloak-authz-client is 3.2.0.Final.

Minutes after posting found the problem. Sorry. I had to perform an EntitlementRequest.
AuthzClient authzClient = AuthzClient.create();
String eat = authzClient.obtainAccessToken("tim", "test123").getToken();
PermissionRequest request = new PermissionRequest();
request.setResourceSetName("testresource");
EntitlementRequest entitlementRequest = new EntitlementRequest();
entitlementRequest.addPermission(request);
EntitlementResponse entitlementResponse = authzClient.entitlement(eat).get("tv", entitlementRequest);
String rpt = entitlementResponse.getRpt();
TokenIntrospectionResponse requestingPartyToken = authzClient.protection().introspectRequestingPartyToken(rpt);
if (requestingPartyToken.getActive()) {
for (Permission granted : requestingPartyToken.getPermissions()) {
System.out.println(granted.getResourceSetId()+" "+granted.getResourceSetName()+" "+granted.getScopes());
}
}
ouputs:
27b3d014-b75a-4f52-a97f-dd01b923d2ef testresource []
Kind regards

Related

How to evaluate permissions with Keycloak authzClient?

I have a protected resource on Keycloak created via remote API with this code:
private fun ProtectedEntity.protect(location: URI, principal: Principal) {
val newResource = ResourceRepresentation()
newResource.name = this.id
newResource.displayName = this.name
newResource.type = "urn:$appName:resources:${this.javaClass.simpleName.toLowerCase().replace("entity", "")}"
newResource.owner = ResourceOwnerRepresentation(this.creator)
newResource.ownerManagedAccess = true
newResource.uris = setOf(location.path.toString())
authzClient.protection().resource().create(newResource)
}
The resource owner is the user who invoked the method and he can manage his own resources.
Now I have to check if a user has permission to access a resource and if not, I guess I should return a ticket in the case the user would like request access to the resource. I tried with this but authorize() throws "Error creating permission ticket".
override fun read(id: ID, principal: Principal): Mono<ResponseEntity<E>> {
val currentUserToken = principal!!.getCurrentUserToken()
val resource = authzClient.protection().resource().findByName(id.toString(), currentUserToken.getUsername())
val token = currentUserToken.tokenValue
val request = AuthorizationRequest()
request.addPermission(resource.id)
request.setRpt(token)
// This returns Error creating permission ticket !?
val response = authzClient.authorization().authorize(request)
val result = authzClient.protection().introspectRequestingPartyToken(response.token)
println(result.active)
if (result.active) {
return super.read(id, principal)
} else throw RuntimeException("Result token RPT is not active!")
}
How I would delegate on Keycloak permission evaluating using authzClient?
The solution is to replace .findByName() by .findByUri(). This endpoint not take into account the resource's owner. I created a gist just in case someone else may need it: ResourceAccessKeycloakWebFilter

eBay GetMyeBaySellings No XML <RequestPassword> or <RequestToken> was found in XML Request

I want to use the eBay-API to get my sold items. Here is my code:
ApiContext apiContext = new ApiContext();
ApiCredential credential = apiContext.getApiCredential();
ApiAccount acc = new ApiAccount();
acc.setApplication("app-id");
acc.setDeveloper("dev-id");
acc.setCertificate("cert");
eBayAccount eBayAccount = new eBayAccount();
eBayAccount.setPassword("ebay user");
eBayAccount.setUsername("ebay password");
credential.setApiAccount(acc);
credential.seteBayAccount(eBayAccount);
apiContext.setApiServerUrl("https://api.ebay.com/wsapi");
GetMyeBaySellingCall call = new GetMyeBaySellingCall(apiContext);
GetMyeBaySellingRequestType requestType = new GetMyeBaySellingRequestType();
call.setMyeBaySellingRequest(requestType);
ItemListCustomizationType lc = new ItemListCustomizationType();
lc.setInclude(new Boolean(true));
lc.setIncludeNotes(new Boolean(true));
lc.setSort(ItemSortTypeCodeType.BID_COUNT);
requestType.setActiveList(lc);
lc = new ItemListCustomizationType();
lc.setInclude(new Boolean(true));
lc.setIncludeNotes(new Boolean(true));
lc.setSort(ItemSortTypeCodeType.PRICE);
requestType.setSoldList(lc);
lc = new ItemListCustomizationType();
lc.setInclude(new Boolean(true));
lc.setIncludeNotes(new Boolean(true));
lc.setSort(ItemSortTypeCodeType.END_TIME);
requestType.setUnsoldList(lc);
lc = new ItemListCustomizationType();
lc.setInclude(new Boolean(true));
lc.setIncludeNotes(new Boolean(true));
lc.setSort(ItemSortTypeCodeType.START_TIME);
requestType.setScheduledList(lc);
call.getMyeBaySelling();
GetMyeBaySellingResponseType resp = call.getReturnedMyeBaySellingResponse();
The APIAccount is configured with the data from the developers site of ebay, the eBayAccount is filled with the credentials of the account I want to fetch items for. However, this results in the following exception:
Exception in thread "main" com.ebay.sdk.SdkSoapException: No XML <RequestPassword> or <RequestToken> was found in XML Request.
at com.ebay.sdk.SdkSoapException.fromSOAPFaultException(Unknown Source)
at com.ebay.sdk.ApiCall.executeByApiName(Unknown Source)
at com.ebay.sdk.ApiCall.execute(Unknown Source)
at com.ebay.sdk.call.GetMyeBaySellingCall.getMyeBaySelling(GetMyeBaySellingCall.java:150)
The user is authenticated for the application and the API-URL is correct. Also, app and user are authenticated for production.
I'd like to give a more detailed example. My app downloads orders from eBay for my account (and my account only). In this case, I do not need to provide App ID, Dev ID or Cert ID. I only need to generate Auth'n'Auth token on eBay and use that as my credential.
Azure function:
#FunctionName("LoadOrders")
public void run(#TimerTrigger(name = "keepAliveTrigger", schedule = "0 5 3 3 * *") String timerInfo, ExecutionContext context)
throws ApiException, SdkException, Exception {
ZonedDateTime startDate = ZonedDateTime.now(Constants.TIMEZONE)
.minusMonths(1)
.with(TemporalAdjusters.firstDayOfMonth())
.withHour(0)
.withMinute(0)
.withSecond(0)
.withNano(0);
ZonedDateTime endDate = ZonedDateTime.now(Constants.TIMEZONE)
.with(TemporalAdjusters.firstDayOfMonth())
.withHour(0)
.withMinute(0)
.withSecond(0)
.withNano(0)
.minusSeconds(1);
GetOrdersCall call = new GetOrdersCall(apiContext());
call.setCreateTimeFrom(GregorianCalendar.from(startDate));
call.setCreateTimeTo(GregorianCalendar.from(endDate));
for (OrderType orderType : call.getOrders()) {
System.out.println(orderType);
}
}
The apiContext() method is defined as follows:
public final static String EBAY_TOKEN = "AgAAAA**AQAA.....a4A9t+/";
public final static String API_SERVER_URL = "https://api.ebay.com/wsapi";
private ApiContext apiContext() {
// credential
ApiCredential credential = new ApiCredential();
credential.seteBayToken(EBAY_TOKEN);
// context
ApiContext apiContext = new ApiContext();
apiContext.setApiCredential(credential);
apiContext.setApiServerUrl(API_SERVER_URL);
apiContext.setCallRetry(callRetry());
return apiContext;
}
And just in case you need it...
private CallRetry callRetry() {
CallRetry retry = new CallRetry();
retry.setMaximumRetries(3);
retry.setDelayTime(3000);
return retry;
}
You can get the "eBay token" at https://developer.ebay.com/my/auth/?env=production (as of 12/25/2019).
Here's what the screen looks like:
ApiContext apiContext = new ApiContext();
ApiCredential credential = apiContext.getApiCredential();
credential.seteBayToken("token from developer central");
apiContext.setApiServerUrl("https://api.ebay.com/wsapi");
GetMyeBaySellingCall call = new GetMyeBaySellingCall(apiContext);

How to add SAS for file services of azure in java?

I got code in c# or code for blob storage. I need some reference code in java to have SAS token for file storage in azure. The SAS may be applicable for account or services.
Code 1 :
static string GetAccountSASToken()
{
// To create the account SAS, you need to use your shared key credentials. Modify for your account.
const string ConnectionString = "DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
// Create a new access policy for the account.
SharedAccessAccountPolicy policy = new SharedAccessAccountPolicy()
{
Permissions = SharedAccessAccountPermissions.Read | SharedAccessAccountPermissions.Write | SharedAccessAccountPermissions.List,
Services = SharedAccessAccountServices.Blob | SharedAccessAccountServices.File,
ResourceTypes = SharedAccessAccountResourceTypes.Service,
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Protocols = SharedAccessProtocol.HttpsOnly
};
// Return the SAS token.
return storageAccount.GetSharedAccessSignature(policy);
}
This code is about creating SAS token for account verification and expiry time.I need the same in java. I am not getting few things like, in first code how I can write the 'Permission' in java? I mean multiple in one line. Please provide equivalent java code for this.
Code 2 :
#Test
public String testFileSAS(CloudFileShare share, CloudFile file) throws InvalidKeyException,
IllegalArgumentException, StorageException, URISyntaxException, InterruptedException {
SharedAccessFilePolicy policy = createSharedAccessPolicy(EnumSet.of(SharedAccessFilePermissions.READ,
SharedAccessFilePermissions.LIST, SharedAccessFilePermissions.WRITE), 24);
FileSharePermissions perms = new FileSharePermissions();
// SharedAccessProtocols protocol = SharedAccessProtocols.HTTPS_ONLY;
perms.getSharedAccessPolicies().put("readperm", policy);
share.uploadPermissions(perms);
// Thread.sleep(30000);
CloudFile sasFile = new CloudFile(
new URI(file.getUri().toString() + "?" + file.generateSharedAccessSignature(null, "readperm")));
sasFile.download(new ByteArrayOutputStream());
// do not give the client and check that the new file's client has the
// correct permissions
CloudFile fileFromUri = new CloudFile(
PathUtility.addToQuery(file.getStorageUri(), file.generateSharedAccessSignature(null, "readperm")));
assertEquals(StorageCredentialsSharedAccessSignature.class.toString(),
fileFromUri.getServiceClient().getCredentials().getClass().toString());
// create credentials from sas
StorageCredentials creds = new StorageCredentialsSharedAccessSignature(
file.generateSharedAccessSignature(policy, null, null));
System.out.println("Generated SAS token is : " + file.generateSharedAccessSignature(policy, null, null));
String token = file.generateSharedAccessSignature(policy, null, null);
CloudFileClient client = new CloudFileClient(sasFile.getServiceClient().getStorageUri(), creds);
CloudFile fileFromClient = client.getShareReference(file.getShare().getName()).getRootDirectoryReference()
.getFileReference(file.getName());
assertEquals(StorageCredentialsSharedAccessSignature.class.toString(),
fileFromClient.getServiceClient().getCredentials().getClass().toString());
assertEquals(client, fileFromClient.getServiceClient());
// self written
// String sharedUri =
// file.generateSharedAccessSignature(policy,null,null);
// System.out.println("token created is : "+sharedUri);
return token;
}
private final static SharedAccessFilePolicy createSharedAccessPolicy(EnumSet<SharedAccessFilePermissions> sap,
int expireTimeInSeconds) {
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
calendar.setTime(new Date());
calendar.add(Calendar.HOUR, expireTimeInSeconds);
SharedAccessFilePolicy policy = new SharedAccessFilePolicy();
policy.setPermissions(sap);
policy.setSharedAccessExpiryTime(calendar.getTime());
return policy;
}
This code is a jUnit test. I don' want to import jUnit library. Want to do it in pure java.How I can convert the code? What I can use instead of assertEqauls?
Please consider the following code snippet in Java.
public static final String storageConnectionString = "DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key";
public String getAccountSASToken() throws InvalidKeyException, URISyntaxException, StorageException {
CloudStorageAccount account = CloudStorageAccount.parse(storageConnectionString);
SharedAccessAccountPolicy policy = new SharedAccessAccountPolicy();
policy.setPermissions(EnumSet.of(SharedAccessAccountPermissions.READ, SharedAccessAccountPermissions.WRITE, SharedAccessAccountPermissions.LIST));
policy.setServices(EnumSet.of(SharedAccessAccountService.BLOB, SharedAccessAccountService.FILE) );
policy.setResourceTypes(EnumSet.of(SharedAccessAccountResourceType.SERVICE));
policy.setSharedAccessExpiryTime(Date.from(ZonedDateTime.now(ZoneOffset.UTC).plusHours(24L).toInstant()));
policy.setProtocols(SharedAccessProtocols.HTTPS_ONLY);
return account.generateSharedAccessSignature(policy);
}

Google App Engine. Stackdriver. Logging with Java

I want to POST Logs to "Custom Logs" of Stackdriver. These feature is beta, and maybe therefore it has no description, how to use Logging with Java API on App Engine. Anyway I want to describe my problem: I use this API version:
"com.google.apis:google-api-services-logging:v2beta1-rev10-1.21.0"
So, first I build the Logging Object like this (I hope this is right):
public static Logging createAuthorizedClient() throws IOException {
// Create the credential
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = GoogleCredential.getApplicationDefault(transport, jsonFactory);
if (credential.createScopedRequired()) {
credential = credential.createScoped(LoggingScopes.all());
}
return new Logging.Builder(transport, jsonFactory, credential).setApplicationName(SharedConstants.APPLICATION_ID).build();
}
After I get the Logging client, I try to push an Entry to the Log:
LogEntry lEntry = new LogEntry();
lEntry.setTextPayload("I want to see this log!");
WriteLogEntriesRequest writeLogEntriesRequest = new WriteLogEntriesRequest();
writeLogEntriesRequest.setLogName("My Super log");
List<LogEntry> listEntries = new ArrayList<>();
listEntries.add(lEntry);
writeLogEntriesRequest.setEntries(listEntries);
Logging logging = LoggingManager.createAuthorizedClient();
Write write = logging.entries().write(writeLogEntriesRequest);
WriteLogEntriesResponse writeLogResponse = write.execute();
But what I get is:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 OK
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid resource id",
"reason" : "badRequest"
} ],
"message" : "Invalid resource id",
"status" : "INVALID_ARGUMENT"
}
=== UPDATE: WORKING SOLUTION ===
Thanks to mshamma. Here is complete code, how to send the data to the logging:
public boolean send() {
WriteLogEntriesResponse response = null;
try {
final String now = getNowUtc();
final String insertId = "entry-at-" + now;
final Map<String, String> labels = ImmutableMap.of("project_id", SharedConstants.APPLICATION_ID, "name",
"projects/" + SharedConstants.APPLICATION_ID + "/logs/" + this.logName);
Logging service = createAuthorizedClient();
MonitoredResource ressource = new MonitoredResource();
ressource.setType("logging_log");
ressource.setLabels(labels);
LogEntry entry = new LogEntry().setInsertId(insertId).setResource(ressource).setTimestamp(now)
.setJsonPayload(this.entriesMap)
.setLogName("projects/" + SharedConstants.APPLICATION_ID + "/logs/" + this.logName)
.setSeverity(this.severity);
WriteLogEntriesRequest content = (new WriteLogEntriesRequest())
.setEntries(Collections.singletonList(entry));
response = service.entries().write(content).execute();
} catch (Exception e) {
}
return response != null;
}
private static String getNowUtc() {
SimpleDateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
return dateFormatUtc.format(new Date());
}
This code works fine with the last version of logging api
Thereby the EntriesMap is:
private Map<String, Object> entriesMap;
I ran into the same issue in the unmanaged Python environment. I got things working and I can see at least two issues in your code.
The log name needs to follow the pattern: "projects/<project-id>/logs/<log-id>". See the documentation of the field here: https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/LogEntry#SCHEMA_REPRESENTATION
You should add a resource descriptor both to the log entry (lEntry) and the write log entry request (writeLogEntriesRequest). In the case of GAE, the resource type field should be set to "gae_app" and you must add three labels to the resource that identify your GAE deployment: "project_id", "module_id" and "version_id".
I hope that will help resolve your issue!

Java client to set SAS, Policy and CORS on Azure

I'm trying to set CORS properties on Azure using Java client. After executing code, I run HTML5 code to upload a file and facing following errors in chrome javascript console:
max block size = 47276
total blocks = 1
https:myacc.blob.core.windows.net/mycon/ch1.jpg?sr=c&sv=2015-04-05&sig=djbVxIBlyVy18bV0SkqNSLql1n9efAVcYnGy3VsGKis%3D&si=champ
current file pointer = 0 bytes read = 47276
block id = block-000000
https:myacc.blob.core.windows.net/mycon/ch1.jpg?sr=c&sv=2015-0…kqNSLql1n9efAVcYnGy3VsGKis%3D&si=champ&comp=block&blockid=YmxvY2stMDAwMDAw
Failed to load resource: the server responded with a status of 403 (CORS not enabled or no matching rule found for this request.)
XMLHttpRequest cannot load
https:myacc.blob.core.windows.net/mycon/ch1.jpg?sr=c&sv=2015-0…kqNSLql1n9efAVcYnGy3VsGKis%3D&si=heath&comp=block&blockid=YmxvY2stMDAwMDAw.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'file://' is therefore not allowed access. The
response had HTTP status code 403.
What I'm wondering is why it didn't set CORS if Java client was executed successfully ? Also, how do I verify if rule Policy "champ" is configured properly, if my generated SAS is correct and CORS properties are created or not
Here is Java Client code:
public class CORS_and_SAS {
public static void main(String[] args) {
// Define the connection-string with your values
final String storageConnectionString ="DefaultEndpointsProtocol=http;" + "AccountName=myacc;" + "AccountKey=B2q4AGp6YoRsTREXIkOv3e/Sxf46YzqzfnM9F8U+o7VA5Y3EiKc+CuritnvuyZxGXKNOQ5nJy2KfkniF970on1dQ==";
try {
// Retrieve storage account from connection-string.
CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString);
// Create the blob client.
CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
// Get a reference to a container.
// The container name must be lower case
CloudBlobContainer container = blobClient.getContainerReference("mycon");
// Create the container if it does not exist.
//container.createIfNotExists();
// Set CORS support
//ServiceProperties blobServiceProperties = blobClient.GetServiceProperties();
ServiceProperties propers = getCORS();
blobClient.uploadServiceProperties(propers);
SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy();
GregorianCalendar calendar =
new GregorianCalendar(TimeZone.getTimeZone("UTC"));
calendar.setTime(new Date());
policy.setSharedAccessStartTime(calendar.getTime()); //Immediately applicable
calendar.add(Calendar.HOUR, 3000); //Applicable time-span is 3000 hours
policy.setSharedAccessExpiryTime(calendar.getTime());
policy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.READ,
SharedAccessBlobPermissions.WRITE, SharedAccessBlobPermissions.DELETE,
SharedAccessBlobPermissions.LIST));
BlobContainerPermissions containerPermissions = new BlobContainerPermissions();
//Private container with no access for anonymous users
containerPermissions.setPublicAccess(BlobContainerPublicAccessType.OFF);
//Name the shared access policy: heath
containerPermissions.getSharedAccessPolicies().put("champ", policy);
container.uploadPermissions(containerPermissions);
//Generate the policy SAS string for heath access
String sas = container.generateSharedAccessSignature(
new SharedAccessBlobPolicy(),"champ");
System.out.println("The stored access policy signature:");
System.out.println(sas);
} catch (Exception e) {
// Output the stack trace.
e.printStackTrace();
}
}
private static ServiceProperties getCORS() {
// TODO Auto-generated method stub
ServiceProperties propers = new ServiceProperties();
CorsProperties corsprop = propers.getCors();
CorsRule cr = new CorsRule();
List<String> allowedHeaders = new ArrayList<String>();
allowedHeaders.add("x-ms-*");
List<String> exposedHeaders = new ArrayList<String>();
exposedHeaders.add("x-ms-*");
cr.setAllowedHeaders(allowedHeaders);
cr.setExposedHeaders(exposedHeaders);
EnumSet<CorsHttpMethods> allowedMethod = EnumSet.of(CorsHttpMethods.PUT,CorsHttpMethods.GET,CorsHttpMethods.POST,CorsHttpMethods.HEAD,CorsHttpMethods.DELETE);
//EnumSet<CorsHttpMethods> allowedMethod1 = EnumSet.of(CorsHttpMethods.GET);
cr.setAllowedMethods(allowedMethod);
List<String> allowedOrigin = new ArrayList<String>();
allowedOrigin.add("*");
cr.setAllowedOrigins(allowedOrigin);
cr.setMaxAgeInSeconds(600);
corsprop.getCorsRules().add(cr);
//corsprop.getCorsRules().add(cr);
propers.setCors(corsprop);
return propers;
}
}
I tried to reproduce the issue, and checked carefully the Java Client code & erros in JS console. I found that the issue was caused by using blob container Shared Access Signature for the uploading file url.
Here is the Java code modified by yours.
private static final String accountName = "<account-name>";
private static final String accountKey = "<account-key>";
private static final String connectionStringTemplate = "DefaultEndpointsProtocol=http;AccountName=%s;AccountKey=%s";
private static final String containerName = "<block-blob-container-name>";
private static final String blobFileName = "<blob-file-name>";
public static void main(String[] args) throws InvalidKeyException, URISyntaxException, StorageException {
String connectionString = String.format(connectionStringTemplate, accountName, accountKey);
CloudStorageAccount account = CloudStorageAccount.parse(connectionString);
CloudBlobClient blobClient = account.createCloudBlobClient();
/*
* Enable CORS
*/
// CORS should be enabled once at service startup
// Given a BlobClient, download the current Service Properties
ServiceProperties blobServiceProperties = blobClient.downloadServiceProperties();
// Enable and Configure CORS
CorsProperties cors = new CorsProperties();
CorsRule corsRule = new CorsRule();
List<String> allowedHeaders = new ArrayList<String>();
allowedHeaders.add("*");
EnumSet<CorsHttpMethods> allowedMethods = EnumSet.of(CorsHttpMethods.PUT, CorsHttpMethods.GET, CorsHttpMethods.HEAD, CorsHttpMethods.POST);
System.out.println(Arrays.toString(allowedMethods.toArray()));
List<String> allowedOrigins = new ArrayList<String>();
allowedOrigins.add("*");
List<String> exposedHeaders = new ArrayList<String>();
exposedHeaders.add("*");
int maxAgeInSeconds = 1800;
corsRule.setAllowedHeaders(allowedHeaders);
corsRule.setAllowedMethods(allowedMethods);
corsRule.setAllowedOrigins(allowedOrigins);
corsRule.setExposedHeaders(exposedHeaders);
corsRule.setMaxAgeInSeconds(maxAgeInSeconds);
cors.getCorsRules().add(corsRule);
blobServiceProperties.setCors(cors);
// Commit the CORS changes into the Service Properties
blobClient.uploadServiceProperties(blobServiceProperties);
/*
* Generate the SAS for the uploading url
*/
CloudBlobContainer container = blobClient.getContainerReference(containerName);
CloudBlockBlob blockBlob = container.getBlockBlobReference(blobFileName);
SharedAccessBlobPolicy sharedAccessBlobPolicy = new SharedAccessBlobPolicy();
GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
calendar.setTime(new Date());
sharedAccessBlobPolicy.setSharedAccessStartTime(calendar.getTime());
calendar.add(Calendar.HOUR, 1);
sharedAccessBlobPolicy.setSharedAccessExpiryTime(calendar.getTime());
sharedAccessBlobPolicy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.WRITE));
String sas = blockBlob.generateSharedAccessSignature(sharedAccessBlobPolicy, null);
System.out.println(sas);
String blobUploadSASURL = String.format("https://%s.blob.core.windows.net/%s/%s?%s", accountName, containerName, blobFileName, sas);
System.out.println(blobUploadSASURL);
}
Run the code and get the uploading blob SAS Url as the form https://<account-name>.blob.core.windows.net/<container>/<blob-file-name>?sig=<SIG>&st=2015-12-01T11%3A51%3A20Z&se=2015-12-01T12%3A51%3A20Z&sv=2015-04-05&sp=r&sr=b
Using PUT method with header x-ms-blob-type: BlockBlob for the URL to upload a file successfully.
Further details and sample ajax code to do this is available, please refer to the blog from the Azure Storage team http://blogs.msdn.com/b/windowsazurestorage/archive/2014/02/03/windows-azure-storage-introducing-cors.aspx.

Categories