I'm working on a solution (not a 3rd party app) that will force active Yammer user to re-authenticate via my Proxy. I have access only to Yammer API.
I would like to know if i can revoke active Yammer user using Yammer API in order to force him to authenticate again and to receive a new token from server?
Can i remove from admin the Auth token for specific user using API and that will force him to re-authenticate and then receive new auth token ?
No, there isn't any API endpoint to force users to re-authenticate to your app. The options that I can think of are: 1. The user will have to manually revoke the app's access from his/her profile page. 2. Create a new app and update the app_id and secret_key in your code. 3. Although I have not tested it, disabling an app may cascade revoke all tokens that are associated with app; for this, you'd need to file a Support case and ask them to disable and re-enable your app.
Related
I have a web app which sends emails (gmail) in name of my users
When a user registers, she supplies gmail account and password. Also she has to enable access for Less Secure Apps (I recommend to create a new account for this)
Then I can open a gmail session
session = Session.getInstance(props, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user.getEmail(), user.getPassword());
}
});
and send emails on her behalf.
Unfortunately this is going to stop working next 30th May, when Google will allow only OAUTH2 access
I have followed Java Quickstart for Gmail API and I have code up and running for sending emails with OAUTH2: enable gmail api, create an application on google cloud platform, grant send permission, oauth2 client id credential created...
The problem I have is I can't see a way to automatize this task because when creating an authorized credential, a consent screen displays on browser and you have to select the account to be granted manually (maybe because my app in google cloud platform is still pending to be reviewed)
Is there a way to infer the gmail account you want to access from the credentials file (client_secret.json)? Is there a way to automatize this?
No, or yes. It depends.
The whole point of OAuth2 is to improve security by working with authorization tokens rather than asking for user credentials. To do this the user has to consent to the app's access request, and thus the OAuth consent screen cannot be bypassed. This is
explained in Google's documentation. It's not related to your app's review status but rather it's the way OAuth works.
You can still work in a similar way, though . Instead of asking for username and password upon the user's registration you can redirect them to the OAuth consent screen so they can authorize your app. Make sure that your app is requesting offline access type and then you can retrieve an access_token and a refresh_token. These will essentially work as your credentials and you can use the refresh token to generate new access tokens when needed without having the user go through the consent screen each time.
The refresh token doesn't have a "natural" expiration so you can keep using it indefinitely, but there are a few scenarios where it will become invalid, such as it not being used for six months, the user changing passwords (if using Gmail scopes), the user manually revoking access, etc. In these cases you will need to direct them to the consent screen again to reauthorize your app.
In this sense, your app can still work automatically without user input except the initial setup, which you already had to deal with when they supplied you with their credentials. The refresh token expiration can even be compared to what you had to do when the users changed their passwords in your current workflow.
One exception to this are service accounts. If you and your users are part of a Google Workspace domain you can delegate domain-wide access to it, then the service account will be able to access user data without any manual input. Of course, this is because as the domain administrator you pretty much own all the accounts under it. But if you're working with a publicly available application you will have to deal with the limitations I mentioned above.
Sources:
Google's auth overview
Using OAuth 2.0 to access Google APIs
OAuth 2.0 for web applications
The OAuth consent screen
I've implemented the OAuth flow in a Teams bot similar to the sample, and I'm able to get a user token and make calls against the graph, but I'm running into an issue with changing permissions. Here's what I did:
Created a bot and gave it mail.read
Add the bot for a user and trigger the OAuth dialog. User is prompted for consent, and signed in.
Successfully read mail
In AAD, added the Mail.ReadWrite and Mail.Send permissions to the app
Next time the OAuthPrompt was triggered, token was returned immediately. No prompt for consent.
Got an access denied exception when trying to write or send mail
So the issue is that changing permissions on the app does not automatically trigger the consent flow again in the OAuthPrompt. I also tried these troubleshooting steps:
I manually signed the user out (botAdapter.SignOutUserAsync) and signed back in, but was not prompted for consent again.
Same as above, but signed out of Teams as well. Launched the web client in a new incognito window, and still no prompt for consent.
Uninstalled and re-installed the bot on the user's account. No change.
Tried the above after waiting a few hours, but still no change.
The only way I found to trigger the consent flow again was to have the user go to https://account.activedirectory.windowsazure.com/r#/applications and delete the consent from there. Even then I had to call botAdapter.SignOutUserAsync (since the bot service still returned a token with the old permissions). Once I did that, and triggered the OAuth prompt again, I was able to get the consent flow with the new permissions to trigger.
So my question is, is there a better way to handle this? If a new version of the bot requires new permissions, shouldn't the OAuthPrompt from Microsoft.Bot.Builder.Dialogs and the bot service handle re-prompting for consent?
Short answer
Bot Framework's auth provider for AAD v1 isn't flexible enough to support adding scopes.
You can switch to the AAD v2 provider and specify your new scopes in the OAuth Connection Settings. Then, if you force the user to sign in again (after SignOutUserAsync), you will get a consent screen including the new scopes. To set up the AAD v2 provider, see the Bot Framework docs on adding authentication to a bot, which has steps for both the AAD v1 and AAD v2 providers.
Long answer
The key to this behavior is how the AAD v1 and AAD v2 endpoints handle permissions and consent differently.
The problem with v1
In v1, the permissions (such as Mail.Send) are pre-registered in the AAD app registration. During sign-in, AAD checks if the user has already consented to any scopes for the app.
If yes, AAD skips the consent screen and eventually provides an access token for the scopes that had already been consented.
If no, AAD shows the consent screen for all registered scopes and eventually provides an access token for all of those scopes.
This explains the behavior you're seeing. After you tell Bot Framework to forget the current access token (via SignOutUserAsync) and force the user to login again, AAD sees that the user has consented previously, so it skips the consent screen and gives you a new token with the old scopes.
Then how do you add permissions for users who have already consented, without forcing the user to delete consent for the app? AAD's login endpoint has an optional prompt parameter that you can set to prompt=consent. This will force AAD to show the consent screen as if the user had not previously consented, and it will contain all registered permissions. So if you try to use an access token and get a 403 Forbidden error (or an equivalent exception), you can take the user through the login flow using prompt=consent.
Unfortunately, with Azure Bot Service's AAD v1 provider, you don't have enough control over the login URL to dynamically set the prompt parameter, so there isn't an easy way to achieve this.
Enter v2
But there's hope! The AAD v2 endpoints have a much more flexible way of adding scopes incrementally. In v2, for delegated permissions, the permissions do not have to be pre-registered in the AAD app registration. Instead, you specify the scopes in the scope parameter of the login URL. During sign-in, AAD checks if the user has consented to the scopes you specified in the URL.
If yes, AAD skips the consent screen and eventually provides an access token for the scopes you specified.
If no, AAD shows the consent screen for all the scopes you specified and eventually provides an access token for all of those scopes.
Either way, you end up with an access token containing all the scopes you specified in the URL.
Bot Framework sets the scope parameter using the scopes you specify in the OAuth Connection Settings. So if you add a new scope there, then the next time the user signs in, they will get a consent screen with the new permissions, and you will get an access token with the new scopes. (Note: To re-trigger the sign-in, you will still have to sign the user out using SignOutUserAsync. Otherwise, Bot Framework will continue giving you the access token it already has, instead of performing a new sign-in flow with AAD.)
I'm making use of the Yammer APIs and embed feed. I was wondering if it was possible to force a sign into Yammer using the user's access token (saved in some local storage). Is it possible to make the yam.getloginstatus() function return true with just the access token, instead of having the user login every time?
There is a setAuthToken() method available which can be used to inject a token. You can continue to authorize a user to your Yammer app and store the token, or use the more advanced approach with impersonation as laid out in the article that is linked. Make sure to create threat models for your application so you have a plan to protect user tokens.
I am looking forward to integrate logging in users using Facebook's authentication. I have my app protected by OpenAM and the users are already registered there. I have my own login page and would not like to move this to OpenAM and retain it in my app. As of now, I am using REST calls to authenticate users in OpenAM. Now, I want to integrate login using Facebook. My idea of implementation is as following:
User logs in using original credentials and is authenticated in
OpenAM.
User is asked to associate his/her Facebook account with the
OpenAM account.
User authenticates his/her Facebook account
(https://www.facebook.com/dialog/oauth?app_id={app-id-as-created-in-fb-developers-console}&redirect_uri={my-rest-service}).
This will return the code and that can be used to recheck against
Facebook to ensure that the user was authenticated against my app
and this is not a hacker intervention
(http://graph.facebook.com/debug_token?%20input_token={code-returned-from-facebook}&access_token={my-app's-access-token}.
The response will contain the app ID that can be verified against my
App's ID. On success, I shall call OpenAM to associate the user in
OpenAM with his/her Facebook credentials (Not sure what all to use
here.)
Next, whenever the user wants to login, he/she can use Facebook
login where in the redirect URL would be my REST service and the
code returned from Facebook can be rechecked from Facebook and then
OpenAM will be called to authenticate.
My queries:
I am not sure if this approach is feasible.
How do I pair an existing user in OpenAM with the Facebook account?
How do I authenticate the user in OpenAM after Facebook login, with
the userID?
Is the Facebook userID (numeric,returned from Facebook graph in JSON
response), unique and permanent?
I would also want to give the users an option to de-associate the
existing Facebook account and associate a new one-how do I do this?
Apologies for asking too many questions, but I am new to OpenAM and OAuth and keen on following the approach I have mentioned above.
Thank you.
As an aside, it will probably be much easier in the future if you delegate all of the login to OpenAM, and let it deal with local login and social. This will make it really easy to add more social providers.
If you want to keep your current architecture, you can create a new authentication chain in OpenAM that just has social (facebook) login. You should be able to redirect the user to that chain. Once the social login process is complete, you can have OpenAM redirect back to your application page.
To link local and social login you are going to have to offer some kind of account claiming in your application. After they do a social login you could ask them to link their local account by providing the username and password. You can call OpenAM's REST API to validate the credentials.
This kind of linking can be confusing for users - so sometimes it is better to treat them as separate accounts, or have a migration process for the user to migrate to social only.
My app allows users to authorize access to their Google Drive via OAUTH. I provide a way to "unlink" their Google Drive from my app. When they request this, I discard their current access token and their refresh token, so things are done from my side.
Is there any way to remove the authorization scopes initially enabled during OAuth from Google's side?
To be specific, I'd like my app to stop being listed for the user on:
https://accounts.google.com/b/0/IssuedAuthSubTokens
I'm not sure if that's a good permanent URL (/b/0/ looks suspicious..)
Yes, you can explicitly revoke the token.
https://developers.google.com/accounts/docs/OAuth2WebServer#tokenrevoke