outlook oauth 2.0 and IMAP - email

I'm trying to achieve the authentication for office 365 accounts by using oauth 2.0 ,
i'm using PublicClientApplication and InteractiveRequestParameters method for acquiring access token and in result successfully received access token ,refresh token and id token but when i am using access_token to connect to imap, i am getting error as authentication failure, can anyone please help me out what am i missing here.
have given all the required permissions from azure portal.
here is my code through which i am trying to connect to server
store.connect("outlook.office365.com", "my_email_id, access_token); //here store is imap
properties i have set are:
properties.put("mail.smtp.port", "587");
properties.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.imap.socketFactory.fallback", "false");
properties.setProperty("mail.imap.port", "993");
properties.setProperty("mail.imap.socketFactory.port", "993");
properties.put("incomingHost", "outlook.office365.com");
properties.put("mail.imap.ssl.enable", "true");
properties.put("mail.smtp.starttls.enable", "true");
properties.put("outgoingHost", "smtp.office365.com");
properties.setProperty("mail.imaps.ssl.trust", "*");
Note: when i am providing password instead of access_token , i am successfully able to login but failure while using access_token.
Thank you !!

You cannot use your access token in place of a password. IMAP requires that your client use SASL XOAUTH2 to authenticate. Details can be found here.
For example, the SASL XOAUTH2 format to access test#contoso.onmicrosoft.com with access token EwBAAl3BAAUFFpUAo7J3Ve0bjLBWZWCclRC3EoAA is:
base64("user=test#contoso.onmicrosoft.com^Aauth=Bearer EwBAAl3BAAUFFpUAo7J3Ve0bjLBWZWCclRC3EoAA^A^A")
After base64 encoding, this translates to the following string. Note that line breaks are inserted for readability.
dXNlcj10ZXN0QGNvbnRvc28ub25taWNyb3NvZnQuY29tAWF1dGg9QmVhcmVy
IEV3QkFBbDNCQUFVRkZwVUFvN0ozVmUwYmpMQldaV0NjbFJDM0VvQUEBAQ==

Related

JWT token exchange via named credentials as per user

I am trying to generate a JSON Web Token(JWT) via named credentials as per user.
I want to use this named creds for authentincation purpose. So that using them after salesforce providing JSON web token, in exchange my local auth server will provide a token.
Below are the settings I have added while creating the named credentials as per user.
Label : TestJWTCredential
Name : TestJWTCredential
URL : -> external-endpoint <-
In Authentication Part
Certificate : MulesoftJWT
Identity Type : Per User
Authentication Protocol : JWT Token Exchange
Token Endpoint Url : http://localhost:8091/api/provider/token
Scope : refresh_token full
Issuer : -> my-username <-
Per User Subject : $userId
Audience : http://localhost:8091/api/provider/token
Token Valid for : 1 Hours
JWT Signing Certificate : MulesoftJWT
Ref :- https://help.salesforce.com/articleView?err=1&id=sf.named_credentials_about.htm&type=5#language-combobox
"http://localhost:8091/api/provider/token" This is the url of my authorization server which is a mule application deployed on my local.
Also while calling this named creds from developer console, it gives this error
System.CalloutException: Unable to complete the JWT token exchange.
Below is the APEX code,
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:TestJWTCredential/services/oauth2/userinfo');
req.setMethod('GET');
req.setHeader('Authorization', 'Bearer'+ UserInfo.getSessionId());
Http http = new Http();
System.debug('REQUEST :::: ' + req);
HTTPResponse resp = http.send(req);
System.debug('RESPONSE :::: ' + resp.getBody());
Can any body help me how to do it.
I was just viewing some Salesforce videos on this topic. In the "Deep Dive into Salesforce Connected App - Part 3" video, at the 23:56 mark, the Salesforce presenter had to delete the "scope" value to get it to work. https://youtu.be/wN8d4vwSA-E?t=1436

authlib: InsecureRequestWarning when fetching token

I am using a flask client to perform openid authentication. However I get the following warning
Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
When fetching the token a request is done using requests.Session.requests here.
Adpating the request method of OAuth2Session fixes the warning.
def request(self, method, url, withhold_token=False, auth=None, **kwargs):
"""Send request with auto refresh token feature (if available)."""
if not withhold_token and auth is None:
if not self.token:
raise MissingTokenError()
auth = self.token_auth
return super(OAuth2Session, self).request(
method, url, auth=auth, verify=True, **kwargs)
Should verification not be enabled by default? Is there a more elegant way to pass verify=True?
You can pass verify directly to the methods of the registered RemoteApp when you fetch the token like this:
token = oauth.remote_app_name.authorize_access_token(verify=True)
I believe SSL verification is enabled by default, however, I use an env var to enable/disable the verification for the requests on a development environment.

AspNet.Security.OpenIdConnect.Server - invalid token when update .net core project

[AspNet.Security.OpenIdConnect.Server] 2.0.0-rc2-final
Doubt about refresh token.
Is there any mechanism so that after updating a .net core project (DLLs), or with the application restart (IIS), a token can be revalidated so that the user remains valid and logged in?
today with each new update of my project, the token is invalidated and the user is disconnected from the application and a new login is required.
after an update the returned message is:
The specified refresh token is invalid.
thanks.
Are you using a developer certificate to sign the token? It seems that you don't use a fixed certificate. The certificate is used to encode and decode the token. If the certificate changes (on restart of the app) then all tokens become invalid.
To set a fixed signing certificate:
var cert = new X509Certificate2("TokenCertificate.pfx", "MySecret",
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
services
.AddAuthentication( ... )
.AddJwtBearer( ... )
.AddOpenIdConnectServer(options =>
{
options.SigningCredentials.AddCertificate(cert);
...
});

Robot Framework api test with OAUTH2 Authorization Request Header

I am trying to use the RequestsLibrary on an api thats using the OAUTH2 authentication.
Authentication is via OAUTH2 with credentials being supplied to the /v1/authtoken endpoint.
Subsequent calls to the APÍ need to have the token included as a ‘bearer’ in the ‘Authorization’ header of the http requests.
So below is the test case. The error I am getting is:
401 != 200
The credentials work ok in jmeter and a list of accounts is returned. However, I am not able to get the RF script work. Any help will be appreciated.
In the script,
Log to Console ${accessToken} returns the access token: 8ETFXTZOWQLrgsMj7c_KuCEeypdj-eO1r...
Log to Console ${token} returns: Bearer 8ETFXTZOWQLrgsMj7c_KuCEeypdj-eO1r...
*** Test Cases ***
Get authToken
Create Session hook http://xxxx.azurewebsites.net verify=${True}
${data}= Create Dictionary grant_type=client_credentials client_id=yyy-zzzz client_secret=xxxxxxxxxxxxxxx
${headers}= Create Dictionary Content-Type=application/x-www-form-urlencoded
${resp}= post request hook /v1/authtoken data=${data} headers=${headers}
Should Be Equal As Strings ${resp.status_code} 200
Dictionary Should Contain Value ${resp.json()} bearer
${accessToken}= evaluate $resp.json().get("access_token")
Log to Console ${accessToken}
${Bearer}= Set Variable Bearer
${token}= catenate Bearer ${accessToken}
Log to Console ${token}
${headers}= Create Dictionary Authorization=${token}
${resp1}= get request hook /v1/integration/accounts headers=${headers}
Should Be Equal As Strings ${resp1.status_code} 200
#Log to Console ${resp1.json()}
I am using OAuth 2.0 authentication as well for my salesforce automation.
My first answer would be to skip client based authentication and switch to username/password based authentication
Get authToken by Password Authentication
RequestsLibrary.Create Session hook https://<url>/services/oauth2 verify=${True}
${data}= Create Dictionary grant_type=password client_id=1abc client_secret=2abc username=test#test.com password=keypass
${headers}= Create Dictionary Content-Type=application/x-www-form-urlencoded
${resp}= RequestsLibrary.Post Request hook /token data=${data} headers=${headers}
Should Be Equal As Strings ${resp.status_code} 200
${accessToken}= evaluate $resp.json().get("access_token")
Log to Console ${accessToken}
If you are using client based or web based authentication, there will be a login screen that will be used by the user to enter their username/password to authorise the app to send requests on its behalf. Have a look at these pages for more information as they primarily discuss about using either refresh tokens or skipping the user prompt altogether.
Why does Google OAuth2 re-ask user for permission when i send them to auth url again
https://salesforce.stackexchange.com/questions/785/authenticate-3rd-party-application-with-oauth2
I have added the new answer for this question.
RequestsLibrary.Create Session OA2 <Your Server URL> verify=${True}
${data}= Create Dictionary Token_Name=TestTokenname grant_type=<grant type> client_Id=<your Id> Client_Secret=<Your client secret> scope=<your scpe>
${headers}= Create Dictionary Content-Type=application/x-www-form-urlencoded
${resp}= RequestsLibrary.Post Request OA2 identity/connect/token data=${data} headers=${headers}
BuiltIn.Log To Console ${resp}
BuiltIn.Log To Console ${resp.status_code}
Should Be Equal As Strings ${resp.status_code} 200
Dictionary Should Contain Value ${resp.json()} Testtokenname
${accessToken}= evaluate $resp.json().get("access_token")
BuiltIn.Log to Console ${accessToken}
${token}= catenate Bearer ${accessToken}
BuiltIn.Log to Console ${token}
${headers1}= Create Dictionary Authorization=${token}
RequestsLibrary.Create Session GT <Your Server URL> verify=${True}
${resp}= RequestsLibrary.Get Request GT <Your API URL> headers=${headers1}
Should Be Equal As Strings ${resp.status_code} 200

MicrosoftAzureMobile.MSClient.loginWithProvider with provider and token failed with return Code=-1505 "The token provided was not valid

There
I'm using MicrosoftAzureMobile ios framework to connect to an azure mobile app with authentication enabled. I configured the service with facebook login. I can successfully login with FBSDKLogin as well as MicrosoftAzureMobile.MSClient.loginWithProvider with provider and controller. However when I try the loginwithProvider with token get from FBSDK,
let accessToken = FBSDKAccessToken.currentAccessToken()
client.loginWithProvider("facebook", token: ["access_token":accessToken]){
I got below error
MicrosoftAzureMobile.MSClient.loginWithProvider with provider and token failed with return Code=-1505 "The token provided was not valid.
how do I debug this issue? the azure portal's tools/streaming logs works last week but always shows connecting today
thanks
Joe
problem solved, i have to use accessToken.tokenString because accessToken itself is not serializable to json