we've created an single-signon with office for our webbapp.
Now we created an app for the office-store, but it was rejected with "Your app does not appear in the ‘My Apps’ launcher after authentication."
What we are currently doing:
send the user to https://login.windows.net/" + Configuration.getOfficeTenant() + "/oauth2/authorize
Fetch a token with the code https://login.microsoftonline.com/" + Configuration.getOfficeTenant() + "/oauth2/token
and then parse the id_token to get users name and email and log him in
How can we controll the "‘My Apps’ launcher" of the user? Do we need to make an additional api call? The page "https://msdn.microsoft.com/en-us/office/office365/howto/connect-your-app-to-o365-app-launcher" does not really point me to a solution - it seems that it should happen autmatically
Related
I have a React SPA which uses msal. I have configured Azure AD as Identity Provider for my AADB2C. I can signIn/signOut and other operations.
If my user signs out off my application, I want to also sign out of my Identity Provider. I looked a bit into this matter 1, 2, 3, 4, 5.
At this moment, I use msal's logoutRedirect method.
const url = new URL(AadEndSessionEndpoint);
url.searchParams.append('post_logout_redirect_uri', SPAUrl);
instance.logoutRedirect({
postLogoutRedirectUri: url.toString()
});
What happens, after my user signs out of my AADB2C, he gets redirected to the AAD end_session_endpoint. I can sign out there as well, but my user gets stuck there. Even though I'm passing the post_logout_redirect_uri query parameter to go back to my app, it ignores it.
How could I make this work?
You are doing an RP Initiated Logout in OpenID Connect terms, meaning you need to also send the id_token_hint query parameter.
I can also confirm that sending both query string parameters logs out successfully for my Azure developer account:
url.searchParams.append('post_logout_redirect_uri', SPAUrl);
url.searchParams.append('id_token_hint', myIdToken);
I think the MSAL library requires you to use getAccount instead:
const account = msalInstance.getAccount();
await msalInstance.logoutRedirect({
account,
postLogoutRedirectUri: "https://contoso.com/loggedOut"
});
UPDATE
Your code above is not right - the post logout redirect URI should be that of your own app - I expect the library already knows the end session endpoint location - so just do this:
instance.logoutRedirect({
postLogoutRedirectUri: SPAUrl
});
At the same time it is worth being aware that the full standards based GET URL should look like this. With the knowledge of the expected URL you can check that you are sending the right request via browser tools:
https://[AadEndSessionEndpoint]?id_token_hint=[myIdToken]&post_logout_redirect_uri=[SPAUrl]
The end session endpoint should be a value such as this by the way:
https://login.microsoftonline.com/7f071fbc-8bf2-4e61-bb48-dabd8e2f5b5a/oauth2/v2.0/logout
I have an app that displays user's instagram media(like some of the dating apps).
Also, my app has been reviewed successfully for permissions - instagram_graph_user_profile and instagram_graph_user_media and is in live mode.
But in the Facebook Developer Console, the instagram icon is not turning up green.
Please refer the screenshot.
https://drive.google.com/open?id=1VnMHLqjTf1oRbvcm2g8Ol80AfB3JqMOg
Flow to display the media is as follows.
1. My app ask users to authorize using
https://api.instagram.com/oauth/authorize?client_id=instagram-app-id&redirect_uri=redirect_uri&scope=scope&response_type=code&state=state
2. Above api responds with a code.Then backend calls -
https://api.instagram.com/oauth/access_token
with params - client_id, client_secret, code, grant_type, redirect_uri
3. Once I receive token from above API, I request long lived token from short-lived token using -
https://graph.instagram.com/access_token?grant_type=ig_exchange_token&client_secret=xyz&access_token=abc
4. Using the long lived token, server requests user info using API -
https://graph.instagram.com/me?fields=id,username&access_token=abc
5. Using the same long lived token, server makes request to get user media using API -
https://graph.instagram.com/me/media?fields=id,media_type,media_url,username,caption,timestamp&access_token=abc
This flow works only for test users(Instagram test users who accepted invitation of being a tester in Instagram Developer Platform).
When non-test user tries to view media, on step 3, I get an error saying -
{ "error": {
"message": "Unsupported get request.",
"type": "IGApiException",
"code": 100,
"fbtrace_id": "A0A24rNXCScki9Ck-8J_55b" } }
Am I missing something?
This is how I see my Business API Settings.
Please refer the screenshot.
https://drive.google.com/open?id=1Dfdihf20krEcYEmoh8z43_a1T5UQStXr
Under my App review section, I do not see any relevant permission that needs to be reviewed again.
Edit 1 -
Note - My app is in beta mode (not yet live on play store).
Could this be the reason?
I just went through a similar process getting my app ready for the old API to officially depreciate. I finally found this— hope it helps:
https://developers.facebook.com/community/threads/2219648518091109/
"After your app has been approved, you can get the contract from your Business Manager. You need to do it on a Computer (mobile wont work) and have to be an Admin on the Business.
From your business Manager you just go to Business Info -> Business Contract (https://business.facebook.com/settings/info)
Please, let us others if this answer helped you!"
Thanks to Juanu for sharing!
In an old application some people in my company were able to get info from Microsoft Graph without signing users in. I've tried to replicate this but I get unauthorized when trying to fetch users. I think the graph might have changed, or I'm doing something wrong in Azure when I register my app.
So in the Azure portal i have registered an application (web app), and granted it permissions to Azure ad and Microsoft graph to read all users full profiles.
Then I do a request
var client = new RestClient(string.Format("https://login.microsoftonline.com/{0}/oauth2/token", _tenant));
var request = new RestRequest();
request.Method = Method.POST;
request.AddParameter("tenant", _tenant);
request.AddParameter("client_id", _clientId);
request.AddParameter("client_secret", _secret);
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("resource", "https://graph.microsoft.com");
request.AddParameter("scope", "Directory.Read.All");
I added the last row (scope) while testing. I still got a token without this but the result is same with or without it.
After I get a token I save it and do this request:
var testClient = new RestClient(string.Format("https://graph.microsoft.com/v1.0/users/{0}", "test#test.onmicrosoft.com")); //I use a real user here in my code ofc.
testRequest = new RestRequest();
testRequest.Method = Method.GET;
testRequest.AddParameter("Authorization", _token.Token);
var testResponse = testClient.Execute(testRequest);
However now I get an error saying unauthorized, Bearer access token is empty.
The errors point me to signing users in and doing the request, however I do not want to sign a user in. As far as i know this was possible before. Have Microsoft changed it to not allow anonymous requests?
If so, is it possible to not redirecting the user to a consent-page? The users are already signed in via Owin. However users may have different access and i want this app to be able to access everything from the azure ad, regardless of wich user is logged in. How is the correct way of doing this nowadays?
Or am I just missing something obvious? The app has been given access to azure and microsoft graph and an admin has granted permissions for the app.
Edit: just to clarify, i tried both "Authorization", "bearer " + _token.Token, and just _token.Token as in the snippet.
Yes, it's still possible to make requests to Graph without a user present using application permissions. You will need to have the tenant admin consent and approve your application.
Edit / answer: Adding the 'Authorization' as a header instead of a parameter did the trick. It works both with 'bearer token' and just 'token'
I am working on some client side web app like a chrome extension that needs access to outlook mail and calendar. I followed the instruction on https://dev.outlook.com/RestGettingStarted and successfully got access and refresh tokens to retrieve data.
However, I cannot find any way of implementing "logout". The basic idea is to let user sign out and login with a different outlook account. In order to do that, I removed cached tokens, requested access tokens in interactive mode. The login window did pop out, but it took any valid email address, didn't let me input password and finally returned tokens for previous account. So I was not able to really use a different account until the old token expired.
Can anyone please tell me if it is possible to send a request to revoke the tokens so people can use a different account? Thanks!
=========================================================
Update:
Actually it is the fault of chrome.identity api. I used chrome.identity.LaunchWebAuthFlow to init the auth flow. It caches user's identity but no way to remove it. So we cannot really "logout" if using this api.
I used two logouts via launchWebAuthFlow - first I called the logout link to my app, then secondly, I called the logout link to Google.
var options = {
'interactive': false,
'url': 'https://localhost:44344/Account/Logout'
}
chrome.identity.launchWebAuthFlow(options, function(redirectUri) {});
options = {
'interactive': false,
'url': 'https://accounts.google.com/logout'
}
chrome.identity.launchWebAuthFlow(options, function(redirectUri) {});
We are building a solution that will need to access our customers Gmail accounts to read/send mail. On account signup, we'd have a pop-up for our customer to do Gmail auth page and then a backend process to periodically read their emails.
The documentation doesn't seem to cover this use case. For example https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth says that client tokens should be stored in client_secrets.json - what if we have 1000s of clients, what then?
Service accounts are for non-user info, but rather application data. Also, if I use the GoogleWebAuthorizationBroker and the user has deleted access or the tokens have expired, I don't want my backend server app to pop open a web brower, as this seems to do.
I would imagine I could use IMAP/SMTP accomplish this, but I don't think it's a good idea to store those credentials in my db, nor do I think Google wants this either.
Is there a reference on how this can be accomplished?
I have this same situation. We are planning a feature where the user is approving access to send email on their behalf, but the actual sending of the messages is executed by a non-interactive process (scheduled task running on an application server).
I think the ultimate answer is a customized IAuthorizationCodeFlow that only supports access with an existing token, and will not execute the authorization process. I would probably have the flow simulate the response that occurs when a user clicks the Deny button on an interactive flow. That is, any need to get an authorization token will simply return a "denied" AuthorizationResult.
My project is still in the R&D phase, and I am not even doing a proof of concept yet. I am offering this answer in the hope that it helps somebody else develop a concrete solution.
While #hurcane's answer more than likely is correct (haven't tried it out), this is what I got working over the past few days. I really didn't want to have to de/serialize data from the file to get this working, so I kinda mashed up this solution
Web app to get customer approval
Using AuthorizationCodeMvcApp from Google.Apis.Auth.OAuth2.Mvc and documentation
Store resulting access & refresh tokens in DB
Use AE.Net.Mail to do initial IMAP access with access token
Backend also uses AE.Net.Mail to access
If token has expired, then use refresh token to get new access token.
I've not done the sending part, but I presume SMTP will work similarly.
The code is based on SO & blog posts:
t = EF object containing token info
ic = new ImapClient("imap.gmail.com", t.EmailAddress, t.AccessToken, AuthMethods.SaslOAuth, 993, true);
To get an updated Access token (needs error handling) (uses the same API as step #1 above)
using (var wb = new WebClient())
{
var data = new NameValueCollection();
data["refresh_token"] = refresh;
data["client_id"] = "(Web app OAuth id)";
data["client_secret"] = "(Web app OAuth secret)";
data["grant_type"] = "refresh_token";
var response = wb.UploadValues(#"https://accounts.google.com/o/oauth2/token", "POST", data);
string Tokens = System.Text.Encoding.UTF8.GetString(response);
var token = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(Tokens);
at = token.access_token;
return at;
}