SSO - Ms Graph and Storage Access - azure-blob-storage

I am currently looking for a SSO solution to access MS Graph and Storage Accounts with a signle interactive user login. When I connect via Connect-AzAccount and grab the token via Get-AzAccessToken it will cut all the required scopes (intune administrator scopes)
Connect-AzAccount
$token = (Get-AzAccessToken -ResourceTypeName MSGraph).token
connects sucessfully but failes when running query below
Connect-MgGraph -AccessToken $token
$GraphURI="https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/?$filter=contains(displayName, '7-Zip - 19.00')"
FAILES no scopes
$GraphResponse = Invoke-RestMethod -Uri $GraphURI -Method "GET" -ErrorAction Stop -Verbose:$false
When I try to other way around (connect via graph and grab the token) those wont match
[Microsoft.Identity.Client.AuthenticationResult]$AccessTokenGraph != [Microsoft.Azure.Commands.Profile.Models.PSAccessToken] $AccessTokenAzAccount
Is there a way to do it? Its important that its done via an interactive login and not via a certficate or app registration.
Thank you!
Eli

Note that : Connect-AzAccount authenticates the user with Azure and this authenticated account can be used only with Azure Resource Manager requests and Connect-MgGraph allows the connection to Microsoft Graph.
I tried to reproduce the same in my environment and got the results like below:
When I tried to connect to Mg Graph by using the access token generated by Get-AzAccessToken I got the error as below:
Connect-AzAccount $token = (Get-AzAccessToken -ResourceTypeName MSGraph).token
Connect-MgGraph -AccessToken $token
$GraphURI="https://graph.microsoft.com/beta/deviceAppManagement/mobileApps
$GraphResponse = Invoke-RestMethod -Uri $GraphURI -Method "GET" -ErrorAction Stop -Verbose:$false
Based on your requirement it is not feasible to have a single interactive user login to access both MS Graph and Storage Accounts. You have to connect AzAccount and MgGraph once at a time as access token of both varies.
You can connect to MgGraph in several ways, and I am able to fetch the details of deviceAppManagement successfully like below:
Reference:
Using Microsoft Graph PowerShell authentication commands

Related

Why my Graph API / cancel outlook meetings call returns always 404 error

I am trying to get all events associated with a user (in order to cancel them). Here is the API doc
I am able through Powershell and Graph API to see a user, and also to sign out this user with the API.
I am using a token got from oauth2 protocol, with grant type client_credentials. I put the permission "Calendars.ReadWrite".
But I only get 404 errors when trying to get the events with :
Invoke-WebRequest 'https://graph.microsoft.com/v1.0/users/864abe35-a43f-44c3-9d24-ea7d2ce53907/events' -ContentType 'application/json' -Method Get -Headers #{Authorization = "Bearer $token"}
This strange thing is that I can get the user array, or revoke his session...
Do this endpoint not working ?
Thank you
EDIT : Answer was that when a user does not have mailboxes, events URL does not exist, and lead to a 404. It works with user having mailbox.
Please provide the full response (with error message etc.).
Have you granted admin consent to Calendars.Write?
In the azure portal, go to Home > App registrations > your app registration and then click on "API permissions". I don't think this is the issue but better to be safe than not. I would rather expect a 403 Forbidden if this is the problem.
Are you sure that the guid of the user is correct? Check if the user with this Id exists in your tenant.
Has the user a valid licence?
Check if the user has a calendar. Use Get calendar.
Maybe the user has only group calendar(s). If this is the case, you need Group.Read.All or Group.ReadWrite.All.
Try to get oulook meetings from a user where you are sure that he has a calendar.
Finally, it appeared that the accounts who do not have any exchange mailbox will not result with an empty return, but with an unexisting URL (that's explains the 404).
It works with an account which holds a mailbox.

Only allow authorized users to access blob urls in an azure storage container

If I configure the access level of a blob to private, the blob url is inaccessible even for those whose AD accounts have been added to the storage account.
How can I allow the blob url to be accessed only by a particular group of users?
According to another stackoverflow link it seems I have to offer access key equivalent information to allow a private blob to be accessed. In such a case, anyone who owns the access key can access the blob as if the access level were public.
According to your need, I suggest you can use Shared access signatures or Azure Active Directory authorization to access your blob. And I do not suggest you share your access key with other people. Because it is not safe. Once someone has the access key, he can directly manage the storage account. For more details, please refer to https://learn.microsoft.com/en-us/azure/storage/common/storage-auth?toc=%2fazure%2fstorage%2fblobs%2ftoc.json
Update
If you want to access privet blob with Azure AD auth, please refer to the following steps
1. Register Azure AD application
Configure Azure APplication
a. Configure permissions
Configure RABC role for the user
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee <email> \
--scope "/subscriptions/<subscription>/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account>
Get token
a. get code
https://login.microsoftonline.com/<tenant>/oauth2/v2.0/authorize?
client_id=<>
&response_type=code
&redirect_uri=http://localhost:3000/
&response_mode=query
&scope=https://storage.azure.com/user_impersonation
&state=12345
b. get token
Post https://login.microsoftonline.com/<>/oauth2/v2.0/token
client_id=<>
&scope=https://storage.azure.com/user_impersonation
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&client_secret=<>
Call Azure blob rest api
Get https://myaccount.blob.core.windows.net/mycontainer/myblob
Headers :
Authorization: Bearer <>
x-ms-version: 2019-02-02
Besides, you also can use sas token to access Azure Blob. For more details, please refer to https://learn.microsoft.com/en-us/rest/api/storageservices/create-service-sas.
For example
$account="blobstorage0516"
$key=""
$container="test"
$blob="test.json"
$context= New-AzStorageContext -StorageAccountName $account -StorageAccountKey $key
Write-host "The blob access level :"(Get-AzStorageContainerAcl -Name test -Context $context).PublicAccess -ForegroundColor red
$sas=New-AzStorageBlobSASToken -Container $container -Blob $blob -Permission r -Context $context
$url="https://${account}.blob.core.windows.net/${container}/${blob}${sas}"
Invoke-WebRequest -Uri $url -Method Get -OutFile e:\test.json
Write-host "download successfully"

Search Console API returns Empty array for site list even though I have several sites in my search console

Search Console API returns Empty array for site list even though I have several sites in my search console.
I have several sites in my search console. When I use the api Explorer, they are returned in the array. Once I use the PHP or Python client library, get an empty result with my Service Account Credentials. This seems to be a permissions issue but the service account I am using has owner role permissions assigned to it, so that doesn't make sense. Any help would be appreciated!
This is my code:
$client = new Google_Client();
$credentials_file = 'path/to/file.json';
$client->setAuthConfig($credentials_file);
$client->setScopes(['https://www.googleapis.com/auth/webmasters']);
$service = new Google_Service_Webmasters($client);
var_dump($service->sites->listSites()->getSiteEntry());
My result: array(0) {}
even though it have several websites in the search console.
Search console sites and site data is considered user data and cannot be accessed by service accounts. You have to make an Oauth 2 interface and save the token to a file and use that token in your app. Make sure the app refreshes the token when it expires:
if ($client->isAccessTokenExpired()) {
$client->refreshToken($this->token['refresh_token']);
$token = $client->getAccessToken(); // save this to a file
}

AAD Authentication Without Interactive Login

I have a need to authenticate against Azure Active Directory from a .net Web API. I read Vittorio Bertucci's article: Using ADAL .NET to Authenticate Users via Username/Password, and was wondering if there's any way of getting around the limitation of not being able to do this from a website/confidential client. He describes this as an AAD setting. Is it one that can be turned off?
Any assistance with this would be much appreciated!
This is not common scenario to use the Resource Owner Password Credentials in a web app. The recommend way is that using the Client Credential flow as Shawn Tabrizi suggested.
If you do want to use the Resource Owner Password Credentials flow, you can construct the request yourself as below:
POST: https://login.microsoftonline.com/xxxxx.onmicrosoft.com/oauth2/token
Content-Type: application/x-www-form-urlencoded
resource={resource}&client_id={clientId}&grant_type=password&username={userName}&password={password}&scope=openid&client_secret={clientSecret}
The Client Credential Flow (App Only Flow) should enable your confidential client to be able to authenticate to a downstream resource without a logged in user. This type of authentication is pure Service to Service Authentication, and will require only a secret for the client app to be presented either in the form of an App Key (symmetric key) or a Certificate Credential (asymmetric key).
However, all forms of access to an AAD Resource will require some form of initial interactive login. In the case of App Only Flows, you will need an Admin to perform an interactive login experience with the Client application, which will then allow subsequent user-less flows.
Check out these sample and let me know if it addresses your question!
https://github.com/azure-samples?utf8=%E2%9C%93&query=daemon
I hope this helps!

Client secret + refreshing the access token in spring oauth2

I am using spring boot for backend and Android device for frontend of my system.
Right now I am facing the challenge to use Spring-OAuth2 to secure my resource server.
I have some questions, which I want to discuss with you:
My knowledge + this tutorial are saying that I should use the OAuth2.0 "password" grant type for my mobile app to obtain an access token. The official spring tutorial for security gives an example how to obtain the access token using password grant type:
$ curl client:secret#localhost:8080/oauth/token -d grant_type=password -d username=user -d password=pwd
And here comes my first question: Is there any possibility to obtain access token using the password grant type without sending the "client secret" ?
Since the client secret could be "reverse engineered" by decompiling the client app. The obtaining access token without secret should be somehow possible, because Facebook SDK for Android also does not need the client_secret in the mobile app.
I think here I have a little trouble understanding why the clientID + clientSecret needs to be included in the request above, because, since there are already username + password included, it should be possible to generate the access token, so does this brings a next level of security ? and does it implies the following (example): I am logged in as Filip in my Android client and I am sending the access token A with each request to the server. Then I log in as Filip into web client and I try to access the resource server from web client using the access token A, which is not possible because access token A was issued only for Android client ?
The next question is how can I refresh the obtained access token ?
I was trying to do so using the command below, but I got "Full authentication is required to access this resource." After I got the new refreshed token, can I use the refresh token to refresh my new access token again ?
curl -v --data "grant_type=refresh_token&client_id=acme&client_secret=acmesecret&refresh_token=REFRESH_TOKEN" http://localhost:9999/uaa/oauth/token
Thank you
The OAuth 2.0 spec allows for so-called public clients i.e. clients that don't authenticate themselves. So it is possible to use the Resource Owner Password Credentials grant with a public client, i.e. one that does not need to send a client secret. It does mean that the Authorization Server cannot assume anything about the client since a client_id is not a secret and there's no way to prevent a malicious client using this grant type or clients from impersonating each other. So using it in this way comes at the cost of reduced security although one may argue that in your case there's no way to use confidential clients anyhow, so there's no difference.
In general the Resource Owner Password Credentials grant is an anti-pattern for OAuth and only meant for migration purposes because it defeats most of the goals of OAuth in itself.
Access tokens are issued on a per-client basis.
You refresh token request seems OK but the Authorization Server may require basic authentication instead of providing the client_id/client_secret as post parameters, considering that you did the same for the original access token request.

Resources