We have a requirement to check the Authorization permissions of an User before executing business logic. I am not able to find an example or tutorial to retrieve the Roles of an User, using Azure Java SDK.
We have Rest API by which we can retrieve all roles assigned to a subscription. Using HTTP request we can retrieve all the role assignments and then we can search for user
Code:
String api = "https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleAssignments?api-version=2015-07-01" ;
// Here substitute the SubstriptionID
System._out_.println( "Hello World!" );
HttpClient client = HttpClient._newHttpClient_();
HttpRequest request = HttpRequest._newBuilder_()
.GET()
.uri(URI._create_(api))
.build();
HttpResponse<String> response = client.send(request , HttpResponse.BodyHandlers._ofString_());
System._out_.print(response.body());
// The following the has to parsed to find whether the user is present or not
Here are the few related Microsoft Documents for complete information.
Role Assignments - List - REST API (Azure Authorization) | Microsoft Docs
Use the Azure SDK for Java | Microsoft Docs
Related
I am new using Azure Graph Rest API Java using this repo.
My aim is to list all of the users in the AAD tenant
So far I was only able to get to this:
List<String> scopes= Arrays.asList("https://graph.microsoft.com/User.Read.All");
AzureProfile profile = new AzureProfile(tenantId, subscriptionId, AzureEnvironment.AZURE);
final ClientSecretCredential credential = new ClientSecretCredentialBuilder()
.clientId(clientId)
.clientSecret(clientSecret)
.tenantId(tenantId)
//.httpClient(client)
.authorityHost(profile.getEnvironment().getActiveDirectoryEndpoint())
.build();
TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(scopes, credential);
GraphServiceClient<Request> graphClient =
GraphServiceClient
.builder()
.authenticationProvider(tokenCredentialAuthProvider)
.buildClient();
UserCollectionPage users = graphClient.users()
.buildRequest()
.get();
for(User user: users.getCurrentPage()){
System.out.println(user.displayName);
System.out.println(user.id);
System.out.println(user.userPrincipalName);
}
However, I run into this error instead:
Caused by: java.io.IOException:
java.util.concurrent.ExecutionException:
com.microsoft.aad.msal4j.MsalServiceException:
AADSTS1002012: The
provided value for scope https://graph.microsoft.com/User.Read.All
openid profile offline_access is not valid. Client credential flows
must have a scope value with /.default suffixed to the resource
identifier (application ID URI).
It seems the Scope that I have used is wrong/insufficient, but I am not too sure what should I use the scope with. Any idea?
It is written in the documentation that:
Client credentials requests in your client service must include
scope={resource}/.default. Here, {resource} is the web API that your
app intends to call, and wishes to obtain an access token for. Issuing
a client credentials request by using individual application
permissions (roles) is not supported. All the app roles (application
permissions) that have been granted for that web API are included in
the returned access token.
The Client Credential flow is best suited for situations where you have a Deamon App that will have to authenticate and get access to some kind of a resource through a Non-Interactive way, which in sequence means that the permissions for this Deamon App have been configured and consented from a step done prior to the auth request.
The /.default scope can be translated as the request of the Background App that runs unattended, to get the bulk of the permissions that it has been configured with and access the resource that it asks.
In plain english, the use of the above scope in the Client Credentials flow is a convention that has to be implemented always when this flow is chosen :P.
I tried to reproduce the same in my environment via Postman and got below results:
I registered one Azure AD application and added API permissions like below:
When I tried to generate access token with same scope as you via Postman using client credentials flow, I got same error as below:
POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
grant_type:client_credentials
client_id: <appID>
client_secret: <secret_value>
scope: https://graph.microsoft.com/User.Read.All openid profile offline_access
Response:
To resolve the above error, you must change your scope to https://graph.microsoft.com/.default if you are using client credentials flow.
After changing the scope, I'm able to generate access token successfully like below:
POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
grant_type:client_credentials
client_id: <appID>
client_secret: <secret_value>
scope: https://graph.microsoft.com/.default
Response:
When I used the above token to call below Graph query, I got the list of users with display name, id and user principal name successfully like below:
GET https://graph.microsoft.com/v1.0/users?$select=displayName,id,userPrincipalName
Response:
In your case, change scope value in your code like below:
List<String> scopes= Arrays.asList("https://graph.microsoft.com/.default");
I've created webapp (not native) in Azure AD. I have java code (adal4j) that
acquire token using appId/appSecret credentials:
String clientId = "xxxxxxxxxxxxxxxxxxxxxx";
String clientSecret = "yyyyyyyyyyyyyyyyyyyyyy";
String resourceUrl = "https://graph.windows.net";
String authorityUrl = "https://login.microsoftonline.com/zzzzzzzzzzzzzzzz/oauth2/authorize";
ExecutorService executorService = Executors.newFixedThreadPool(4);
Optional<UserInfo> userInfo = Optional.empty();
try {
AuthenticationContext authContext = new AuthenticationContext(authorityUrl, false, executorService);
Future<AuthenticationResult> future = authContext.acquireToken(resourceUrl, new ClientCredential(clientId, clientSecret), null);
AuthenticationResult result = future.get();
}
Now I would like to check if specified user/password combination is in Azure AD and if yes then get First and Last name of this user.
Is it possible to do this usinq acquired token ? How to write such code using adal4j ?
It sounds like what you're really trying to do is sign in a user and get their first/last name. As the comment said, the pattern suggested is not a valid one and would represent a security issue. Additionally, the use for clientId and clientSecret is not exactly for user credentials, but for app credentials. This is used for flows without user interaction for service/api applications, and doesn't sound like what you'll want.
Now, to achieve this you'll be using the OpenID Connect protocol. To simplify what will happen, your app (upon user trying to sign in) will redirect to the Microsoft sign in page (https://login.microsoftonline.com), enter their credentials and fulfill any other authorization requirements, consent to your app, and then redirected back. When they come back, your app will receive an ID Token which can be validated and used to get information about the user that has just sign in. During this time, Azure AD / Microsoft will also set a cookie on the browser so the user will get SSO across their account.
In terms of how to achieve this, I recommend following the ADAL4J Code Sample. This will get your app an ID Token, and also an Access/Refresh token that you can use to call the Microsoft Graph API. This API can also get you information about the user (basic profile info), but also their Office365, Intune, and Windows data.
I am trying to get the user email, that I used to log in with when performing Oauth2 through Youtube in my application. The code is similar to this:
YouTube client = new YouTube.Builder(GoogleNetHttpTransport.newTrustedTransport(), JacksonFactory
.getDefaultInstance(), credential)
.setApplicationName("app_name").build();
YouTube.Channels.List channelListByIdRequest = client.channels().list("snippet,contentDetails,statistics");
channelListByIdRequest.setMine(true);
ChannelListResponse channelListResponse = channelListByIdRequest.execute();
Here I pull the channel api, that, according to the doc is some kind of similar to the user api in v3. However, neither in Channel nor in any other API I cannot find how to get the email I logged in with. How can that information be accessed?
I have done some research and, unfortunately, there is indeed no possibility to fetch the email. As far as I understand, it is against the concept of Youtube and its data API - it deals with channels and multiple of those can be associated with a single email.
Used this for reference:
https://developers.google.com/youtube/v3/getting-started
However, you can use Google plus API scopes along with Youtube scopes to fetch the user info (but we need to take into account that it will be discarded by March 7, 2019)
GoogleNetHttpTransport.newTrustedTransport(), JacksonFactory.getDefaultInstance(), clientSecrets,
Arrays.asList(YouTubeScopes.YOUTUBE_FORCE_SSL, PlusScopes.PLUS_ME, PlusScopes.USERINFO_EMAIL))
.setAccessType("offline").setApprovalPrompt("force").build();
We will be prompted to select email and channel in Oauth window and will be able to fetch the info.
I am working on Google Sheets <-> Salesforce integration and developing it in Salesforce programming language - Apex on Force.com platform.
Currently I am attempting to connect to Google Sheets API. I am using Service Account Key, so Salesforce can pull the data from Google Sheets without the requirement for manual authorisation every time it sends out a query.
I am at the point where I set up the Service Account Key and I am successfully sending a request to it to obtain the access_code.
Then I am attempting to query the API, using the following class:
/****** API CALLOUT *******/
public static HttpResponse googleSheetsCallout (){
//the below line provides a string containing access token to google
string accessCode = getAccessToken();
//I found this endpoint structure online, this may be why my script
//isn't working. However, I am struggling to find the alternative.
string endpoint = 'https://sheets.googleapis.com/v4/spreadsheets/params=[SPREADSHEET ID GOES HERE]/values/[RANGE GOES HERE]?access_token=';
httpRequest req = new httpRequest();
req.setEndpoint(endpoint+accessCode);
req.setMethod('GET');
req.setTimeout(120000);
httpResponse res = new http().send(req);
System.debug ('res is ' +res);
return res;
}
When I run the function this is what the log returns:
|CALLOUT_RESPONSE|[71]|System.HttpResponse[Status=Forbidden, StatusCode=403]
|USER_DEBUG|[72]|DEBUG|res is System.HttpResponse[Status=Forbidden, StatusCode=403]
I enabled Google Sheets access in the google developer console menu, and what's interesting is when loking at the console it appears that Google notices API requests being sent out (they are appearing on the activity chart).
I solved it, and the issue was not the code itself.
The problem was sharing my sheet. To allow read/edit access to your sheet from the service account it must be shared with the Service Account ID email address, the same way it's shared with any other user. If this isn't done the script will produce 403 error.
I am using Magento with a 3rd party Java Web Application.
My application is "connected" to Magento via Magento SOAP API V2.
How can I perform a Customer Authentication from my Java aplication (outside of Magento) via api?
Any help would be appreciated.
I came up to a solution on how to login a customer via SOAP API and I will post it here so it can be helpful for others.Here is what I did to make it work:
I created a custom module in Magento with a custom method that login a customer and retuns the sessionID that is set on server side.
Mage::app()->setCurrentStore($website);
// Init a Magento session. This is super ultra important
Mage::getSingleton('core/session');
// $customer Mage_Customer_Model_Customer
// We get an instance of the customer model for the actual website
$customer = Mage::getModel('customer/customer')
->setWebsiteId(Mage::app()->getStore()->getWebsiteId());
// Load the client with the appropriate email
$customer->loadByEmail($email);
// Get a customer session
$session = Mage::getSingleton('customer/session');
$session->loginById($customer->getId());
if ($session->isLoggedIn()) {
return $session->getSessionId();
} else {
return null;
}
I created a Magento Custom Api so I can call my login method via SOAP.
Call the login method from my JAVA app, get the sessionId, then set the cookies on the browser, based on received sessionId.
http://yourmagentohost/setCookies.php?sessionId=your_session_id
And inside setCookies.php you have: setcookie("frontend", $_GET["sessionId"] , time()+3600);
That's it, now you have a logged in customer.
How can I perform a Customer Authentication from my Java aplication
(outside of Magento) via api? SOAP API V2
Clarification:
API Users (at least Soap) and Customer's are two user types. If you have a pre-existing userlist, and are looking to find out if they exist as user's inside of Magento, you may retrieve email account's and their related attributes and corresponding password hash's (CE: md5:salt , or CE/EE: sha:salt) all via SOAP. If you are looking to do comparative operations, you will need to implement the same Hashing against your password's to do 1:1 comparisons. If you are looking to have your Application use SOAP to directly perform operations, I would make sure that there is a layer of abstraction, as your app could be used nefariously targeting other user id's all depending on the SOAP Role and ACL set in Magento's Admin.
Moving on...
V2: You'll have to swap to Java, ex: PHP.
$username 'yourUsername';
$password = 'yourApiKeyPlainText';
$proxy = new SoapClient('https://www.yourdomain.com/magento/api/v2_soap?wsdl=1');
$sessionId = $proxy->login($username, $password);
//Get a Full customer List from Magento
$customerList = $proxy->customerCustomerList($sessionId);
//get back a list
//Target a user from your List, Compare Details against your App
$customerInfo = $proxy->customerCustomerInfo($sessionId, '2'); //Customer Id
Remote operations, like Checkout, can be rather involved. The question remains, what do you wish to do next to, or on behalf of the user with your app?
References:
http://www.magentocommerce.com/api/soap/customer/customer.list.html
http://www.magentocommerce.com/api/soap/customer/customer.info.html
Cheers,
Your code example does not use SOAP. Magento SOAP accesses actually look like the following:
$client = new SoapClient('http://magentohost/soap/api/?wsdl');
// If somestuff requires api authentification,
// then get a session token
$session = $client->login('apiUser', 'apiKey');
Have a look at the API documentation: http://www.magentocommerce.com/api/soap/introduction.html