My code is below. credential contains a token.
Settings contains a subtoken and the application name, but nothing else.
I am not sure if it is authenticating. Token, token secret, privatekey are all nothing.
Dim _Scopes As New List(Of String)
_Scopes.Add("https://www.google.com/m8/feeds")
_Scopes.Add("http://www.google.com/m8/feeds/contacts/")
_Scopes.Add("https://www.googleapis.com/auth/contacts.readonly")
Dim certificate As X509Certificate = New X509Certificate2("c:\sites\key.p12", "notasecret", X509KeyStorageFlags.Exportable)
Dim serviceAccountEmail As String = "serviceaccountemailhere"
Dim credential As ServiceAccountCredential = New ServiceAccountCredential(New ServiceAccountCredential.Initializer(serviceAccountEmail) With {.User = serviceAccountEmail, .Scopes = _Scopes}.FromCertificate(certificate))
Dim settings As RequestSettings = New RequestSettings("Gmail Contact APP", Await credential.GetAccessTokenForRequestAsync())
Dim cr As New ContactsRequest(settings)
For Each ct In cr.GetContacts.Entries
Console.Write(ct.ContactEntry.Name)
Next
Related
Following the changes, I try to connect and send mails via EAGetMail/EASendMail.
The connection is good, I have good access to the token and also to my mailbox.
However, when I want to send an email via "smtp.office365.com" I get an error: 535 5.7.3 Authentication unsuccessful.
I do not understand where the error can come from, I take the same token as when connecting to the mailbox.
Below is just the code to send emails, I have a token and it works perfectly to connect to my email
If someone has a project that works with smtp and Oauth 2.0 (without using a browser)...
Module Module1
Sub Main(ByVal args As String())
Try
RetrieveEmail()
Catch ep As Exception
Console.WriteLine(ep.ToString())
End Try
Console.ReadKey()
End Sub
Function _generateFileName(ByVal sequence As Integer) As String
Dim currentDateTime As DateTime = DateTime.Now
Return String.Format("{0}-{1:000}-{2:000}.eml",
currentDateTime.ToString("yyyyMMddHHmmss", New CultureInfo("en-US")),
currentDateTime.Millisecond,
sequence)
End Function
Function _postString(ByVal uri As String, ByVal requestData As String) As String
Dim httpRequest As HttpWebRequest = TryCast(WebRequest.Create(uri), HttpWebRequest)
httpRequest.Method = "POST"
httpRequest.ContentType = "application/x-www-form-urlencoded"
Using requestStream As Stream = httpRequest.GetRequestStream()
Dim requestBuffer As Byte() = Encoding.UTF8.GetBytes(requestData)
requestStream.Write(requestBuffer, 0, requestBuffer.Length)
requestStream.Close()
End Using
Try
Dim httpResponse As HttpWebResponse = TryCast(httpRequest.GetResponse(), HttpWebResponse)
Using reader As New StreamReader(httpResponse.GetResponseStream())
Dim responseText = reader.ReadToEnd()
Return responseText
End Using
Catch ex As WebException
If ex.Status = WebExceptionStatus.ProtocolError Then
Dim response = TryCast(ex.Response, HttpWebResponse)
If response IsNot Nothing Then
Console.WriteLine("HTTP: " & response.StatusCode)
' reads response body
Using reader As StreamReader = New StreamReader(response.GetResponseStream())
Dim responseText As String = reader.ReadToEnd()
Console.WriteLine(responseText)
End Using
End If
End If
Throw ex
End Try
End Function
Public Sub RetrieveEmail()
Try
Dim client_id As String = "XXXXXXXXXXXXXXXXXXXX"
Dim client_secret As String = "XXXXXXXXXXXXXXXXXXXXXXXXX"
' If your application is not created by Office365 administrator,
' please use Office365 directory tenant id, you should ask Offic365 administrator to send it to you.
' Office365 administrator can query tenant id in https://portal.azure.com/ - Azure Active Directory.
Dim tenant As String = "XXXXXXXXXXXXXXXXXX"
Dim requestData As String = String.Format("client_id={0}&client_secret={1}&scope=https://outlook.office365.com/.default&grant_type=client_credentials",
client_id, client_secret)
Dim tokenUri As String = String.Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", tenant)
Dim responseText As String = _postString(tokenUri, requestData)
Dim parser As EASendMail.OAuthResponseParser = New EASendMail.OAuthResponseParser()
parser.Load(responseText)
Dim officeUser As String = "tma#XXXX.fr"
Dim oServerSend As SmtpServer = New SmtpServer("smtp.office365.com")
oServerSend.ConnectType = SmtpConnectType.ConnectSSLAuto
oServerSend.Port = 587
oServerSend.AuthType = SmtpAuthType.XOAUTH2
oServerSend.User = officeUser
oServerSend.Password = parser.AccessToken
Dim oMailSend As SmtpMail = New SmtpMail("TryIt")
oMailSend.From = "tma#XXX.fr"
' Please change recipient address to yours for test
oMailSend.[To] = "XXXXXXXXXXX"
oMailSend.Subject = "test email from Hotmail account with OAUTH 2"
oMailSend.TextBody = "this is a test email sent from VB.NET project with Hotmail."
Console.WriteLine("start to send email using OAUTH 2.0 ...")
Dim oSmtp As SmtpClient = New SmtpClient()
oSmtp.SendMail(oServerSend, oMailSend)
' Quit and expunge emails marked as deleted from server.
Console.WriteLine("Completed!")
Catch ep As Exception
Console.WriteLine(ep.ToString())
End Try
End Sub
End Module
In Docusing I am obtained access token with demo account successfully and create envelope also, when I move to production account, I can't get access token and got error as "The remote server returned an error: (400) Bad Request." I did 20 API calls successfully and reviewed and make Go to live from developer account, API key details reflects on production login also.
Old Code
This is the code I used to obtain access token.
Dim PrivateKey As String = odjDTRep.Rows(0)("PrivateKey").ToString().Trim.Replace(vbLf, "").Replace(vbCr, "")
'This section to generate jwt Header
Dim ar1 As JObject = New JObject()
ar1.Add("typ", "JWT")
ar1.Add("alg", "RS256")
Dim header As String = Base64UrlEncoder.Encode(ar1.ToString)
'This section to generate jwt Body
Dim ar2 As JObject = New JObject()
ar2.Add("iss", odjDTRep.Rows(0)("iss_Int_Key").ToString())
ar2.Add("sub", odjDTRep.Rows(0)("sub1_Api_UserName").ToString())
ar2.Add("iat", DateDiff(DateInterval.Second, New Date(1970, 1, 1), Now().ToUniversalTime))
ar2.Add("exp", DateDiff(DateInterval.Second, New Date(1970, 1, 1), DateAdd(DateInterval.Hour, 1, Now().ToUniversalTime)))
ar2.Add("aud", odjDTRep.Rows(0)("aud").ToString())' aud i pass account.docusign.com
ar2.Add("scope", odjDTRep.Rows(0)("scope").ToString())
Dim body As String = Base64UrlEncoder.Encode(ar2.ToString)
Dim stringToSign As String = header & "." & body
Dim bytesToSign() As Byte = Encoding.UTF8.GetBytes(stringToSign)
Dim keyBytes() As Byte = Convert.FromBase64String(PrivateKey)
Dim privKeyObj = Asn1Object.FromByteArray(keyBytes)
Dim privStruct = RsaPrivateKeyStructure.GetInstance(privKeyObj)
'This section to generate jwt Signature
Dim sig As ISigner = SignerUtilities.GetSigner("SHA256withRSA")
sig.Init(True, New RsaKeyParameters(True, privStruct.Modulus, privStruct.PrivateExponent))
sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length)
Dim signature() As Byte = sig.GenerateSignature()
Dim sign As String = Base64UrlEncoder.Encode(signature)
Dim a As String = header & "." & body & "." & sign
ServicePointManager.Expect100Continue = True
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
ServicePointManager.SecurityProtocol = DirectCast(3072, SecurityProtocolType)
ServicePointManager.Expect100Continue = True
Dim request As WebRequest = WebRequest.Create("https://account.docusign.com/oauth/token?grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=" & a & "")
request.Method = "POST"
request.ContentType = "application/x-www-form-urlencoded"
request.ContentLength = 0
request.Headers.Add("X-DocuSign-Authentication", "{ ""Username"":""" & odjDTRep.Rows(0)("UserName").ToString() & """, ""Password"":""" & odjDTRep.Rows(0)("Password").ToString() & """, ""IntegratorKey"":""" & odjDTRep.Rows(0)("iss_Int_Key").ToString() & """ }")
Dim response As WebResponse = request.GetResponse()
Console.WriteLine((CType(response, HttpWebResponse)).StatusCode)
If (CType(response, HttpWebResponse)).StatusCode <> HttpStatusCode.OK Then
Return "002:Fail"
End If
Dim dataStream As Stream = response.GetResponseStream()
Dim reader As New StreamReader(dataStream)
Dim responseFromServer As String = reader.ReadToEnd()
reader.Close()
response.Close()
All details I read from SQL table and store in DataTable, from DataTable I pass all details in that code. Any other URL I need change above I mention for production environment?
New code to obtain Access token
var apiCent = new ApiClient("https://demo.docusign.net/restapi");
string ik = "xxxx-6a8b-4a7d-ba0f-xxxx";
string userId = "xxxxx-db97-xxx-a398-0e5986fadf49";
string accountId = "xxxxx-3e10-42af-xxxxx-xxxx";
string envId = "";
string authserver = "account.docusign.com";
string rsaKey = "xxxxxxxxxi7+b8i7SmfRdx8sExxxxxxxKmwIbLFOv1LtmUk/KRP8wPmMeNpq10kAzizzAeqnuBgW9ECHjV/gUA984dzk128UPmIRqTW+69e1dSknGA+nJWshyZEqJXmvFB8Ueie5EiCW6FIlXpdLVWwmJwUGiQQsV+r8hpmbhSImr5A40HQPPpasYAnKPNDgRbKwxrOONrCdUUre34Up2sk8gcAcMQRwKosPBn6/dAXadYP0sKEGSVKogguNSCyoHOLh74MPepDLnEVs9VAiyk+zQEmZxYaXhrV4pvO2C5WNXdnqHUdcC/McZOBVGwRdG0xOaC8t4lplJHjiis+8YQEWQIDAQABAoIBACTzxYJBBWGtVXRyqo+jzqmSOKJrBumvtHlC6k7IvYYInJI3IVPV44pC+eROAdDiYgQE9LZvag2MW7A8IAeYwWJZhBKCq8odz4plgJaZwX2YdItDP4kSjIOco5W4lMjMQd66KNMTKFkS2fgbtBF0crogO8cuAwn+kZtsdFH8IKA+LPQjvp09yXZvDN6Q8XTKfcIkW2TqthdUOcJP65h72KwQnQGGvTDAd8p3OsHqAt7LEwW6xg0ci2HT1fGZbdwrXVHFHX9mFPndLmQ1CZlwX8XiVIHYPdbEEjO+3U29jGsi/k8+h54ngcf5H1An8t+fdDVzknprbCGOIdynnLFq0CgYEA1os/qHEXObHe+Yn2EQWM924hPtOjY5Z6p60EEALaaKVLYiCyhI7fXkhfB0475gC0+HhGgyu0zts04iOE2Agr8Yc8jAkZ3/UGOrbBFoSSyHvKYQaYqdWJ4HjbV3L5jkWSzplmn5/KFM9COMecEpx0cXkhxt1MMC5gu3WKU5QWhMcCgYEAvdLlwOf33KUsG/dojZAtzK6Lz6UoBi+nHHg9jZ2V561xSzhrGGBTRkpUL5kf66AOrHRNYZvNX051WCzsQ94NBOzgwykhqcC+gYBx6ravoBgyyrw/YICQB69xkxJlq/uGZQf3cvcPfcxFbjySzjCqgmgXewmqJE2U0drnhDVzd8CgYBOGViuB6UNwptJuZgSsDOVqsh9Z2t2CERUH553+aHqMCnV6dMygBP97Vhyf188pgs63AXHIDTsjE2e+JEWVzsv7Cv1SibaKQcAfqChgtcwFigg09blFC/hv/0Qw3DnApqjjKIX/4H/u0b/BmLhP4T//bl2+/4NGATsmKgnLqRX5wKBgBFP36ZVQZS896XhTYbDpHmrXZLldB4EUJBXIv38ZkSH2/JJRfMmLdIWS1E//NpHca8muDvzsqpDhJn7qMe4KnVNaqzEBWlGaA4XaCgmm+aN3MYKt4nXRo9EfnhMUtXMW8G3caSPyBlapv5dLLPRjGdnk1mdhPUQsUytEdKLpIQvAoGAbcb1rHbHv9AlmBBq5JODGgfN9GbLpPR6KyCtUGPhIrcSyZF00PcIEckwwt1XvqFJXFzFWCs9SEq7YbmGKuxSVZ7NLOOLaX6lZ3HdBiHvqcsCdMiqw9egTqqkn2po7pGCQzwxYmGLBfF+MXDo3KTynvNMz31efrZlmQsVq3VBt9U=";
var scopes = new List<string>
{
"signature"
};
OAuth.OAuthToken authToken = apiCent.RequestJWTUserToken(ik, userId, authserver,Encoding.UTF8.GetBytes(rsaKey), 1, scopes);
string accessToken = authToken.access_token;
Now i am getting error as "Unexpected PEM type" , in production account i take IK,UserID and generated new RSA key.
First off, using legacy auth is not allowed for new applications. You are using the X-DocuSign-Authentication header with clear text password which is a legacy mechanism to authenticate. It is insecure and cannot be used.
When using JWT authentication and changing from the developer environment to the production environment you have to do the following:
Pass go-live and get approval to have your IK (app) in production.
Promote your IK to your production account.
Create a new RSA key for the new IK in the production account. You cannot use the RSA key from your developer account.
The URL for authentication is changed from https://account-s.docusign.com to https://account.docusign.com
userId for the user will be different GUID - need to update
accountId for the account will be different GUID - need to update
I am writing a windows service application in Visual Studio (VB) that polls a users google calendar for any events that are happening within the next 5 minutes.
Ideally, I'd like my service to generate the credentials, but I don't think a windows service can pop up a browser page to authenticate someone. Currently I am generating the credentials in a specific location from a console app that can pop up a browser, and having the service look for credentials in that location. I'd like to get rid of the console app altogether, but if it's necessary I'll just run it in the batch file that installs the service.
The big issue I'm having is generating the credentials file (secondary concern), and more importantly refreshing it so it doesn't expire after an hour (primary concern).
Here is my windows service code (this works perfectly fine for the hour after I run my console app and allow access to my calendar):
Dim Scopes As String() = {CalendarService.Scope.CalendarReadonly}
Dim ApplicationName As String = "Google Calendar API .NET Quickstart"
Private Sub writeUpdateTimerEvent(source As Object, e As ElapsedEventArgs)
Dim credential As UserCredential
Try
Using stream = New FileStream("FILE PATH TO client_secret.json", FileMode.Open, FileAccess.Read)
Dim credPath As String = "FILE PATH TO WHERE MY CONSOLE APP IS STORING THE CREDENTIALS FILE"
credPath = Path.Combine(credPath, ".credentials/calendar-dotnet-quickstart.json")
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, Scopes, "user", CancellationToken.None, New FileDataStore(credPath, True)).Result
If credential Is Nothing Then
credential.RefreshTokenAsync(CancellationToken.None)
End If
End Using
' Create Google Calendar API service.
Dim service = New CalendarService(New BaseClientService.Initializer() With {
.HttpClientInitializer = credential,
.ApplicationName = ApplicationName
})
' Define parameters of request.
Dim request As EventsResource.ListRequest = service.Events.List("primary")
request.TimeMin = DateTime.Now
request.TimeMax = DateTime.Now.AddMinutes(5)
request.ShowDeleted = False
request.SingleEvents = True
request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime
' List events.
Dim eventsString As String = ""
Dim events As Events = request.Execute()
If events.Items IsNot Nothing AndAlso events.Items.Count > 0 Then
'This is where I do my operations on events occuring in the next 5 minutes
EventLog1.WriteEntry("Event occuring within 5 minutes")
Else
EventLog1.WriteEntry("No event occuring within 5 minutes")
End If
Catch ex As Exception
EventLog1.WriteEntry("error grabbing events." & Environment.NewLine & ex.message)
End Try
End Sub
Here is my console app code (pretty much the same as above):
Module Module1
Dim Scopes As String() = {CalendarService.Scope.CalendarReadonly}
Dim ApplicationName As String = "Google Calendar API .NET Quickstart"
Sub Main()
Dim credential As UserCredential
Using stream = New FileStream("client_secret.json", FileMode.Open, FileAccess.Read)
Dim credPath As String = "SAME FILE PATH AS IN MY SERVICE"
credPath = Path.Combine(credPath, ".credentials/calendar-dotnet-quickstart.json")
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, Scopes, "user", CancellationToken.None, New FileDataStore(credPath, True)).Result
Console.WriteLine(Convert.ToString("Credential file saved to: ") & credPath)
End Using
' Create Google Calendar API service.
Dim service = New CalendarService(New BaseClientService.Initializer() With {
.HttpClientInitializer = credential,
.ApplicationName = ApplicationName
})
' Define parameters of request.
Dim request As EventsResource.ListRequest = service.Events.List("primary")
request.TimeMin = DateTime.Now
request.ShowDeleted = False
request.SingleEvents = True
request.MaxResults = 10
request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime
' List events.
Dim events As Events = request.Execute()
Console.WriteLine("Upcoming events:")
If events.Items IsNot Nothing AndAlso events.Items.Count > 0 Then
For Each eventItem As Object In events.Items
Dim [when] As String = eventItem.Start.DateTime.ToString()
If [String].IsNullOrEmpty([when]) Then
[when] = eventItem.Start.[Date]
End If
Console.WriteLine("{0} ({1})", eventItem.Summary, [when])
Next
Console.WriteLine("You may now close this window.")
System.Environment.Exit(0)
Else
Console.WriteLine("No upcoming events found.")
End If
Console.Read()
End Sub
End Module
Got it working now, using a service account instead of a user account. No need for dealing with generating credentials or refreshing the token.
Dim serviceAccountEmail As [String] = ConfigurationManager.AppSettings("ServiceAcct")
Dim certificate = New X509Certificate2("key.p12", "notasecret", X509KeyStorageFlags.Exportable)
Dim credential1 As New ServiceAccountCredential(New ServiceAccountCredential.Initializer(serviceAccountEmail) With {
.Scopes = Scopes
}.FromCertificate(certificate))
Dim service = New CalendarService(New BaseClientService.Initializer() With {
.HttpClientInitializer = credential1,
.ApplicationName = ApplicationName
})
the following VB.net code is working to authenticate to a web service - and it works great however i am having to use default network Credentials ( the logged in user the code runs under )
I would like to pass network Creds to the web service and the following should work but does not. This is the working code using default credentials.
Dim URL As String = "http://server/MBSDKService/MsgSDK.asmx?WSDL"
Dim myService As New LANDeskMBDSK.MBSDK
myService.Url = URL
Dim CredCache As New System.Net.CredentialCache
myService.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials
This is what i want to work but does not...
Dim URL As String = "http://server/MBSDKService/MsgSDK.asmx?WSDL"
Dim myService As New LANDeskMBDSK.MBSDK
myService.Url = URL
Dim Cred As New System.Net.NetworkCredential("domain\user", "password")
Dim CredCache As New System.Net.CredentialCache
CredCache.Add(New Uri(myService.Url), "Basic", Cred)
myService.Credentials = CredCache
Does anyone know what I am doing wrong?
The rest of the code works perfectly so it is a case of what i have to add to the above to get it to work like the default credentials do.
Thanks!
Thanks to George this is the solution...
Dim URL As String = "http://server/MBSDKService/MsgSDK.asmx?WSDL"
Dim myService As New LANDeskMBDSK.MBSDK
myService.Url = URL
Dim Cred As New System.Net.NetworkCredential("user", "password")
Dim CredCache As New System.Net.CredentialCache
CredCache.Add(New Uri(myService.Url), "Basic", Cred)
myService.Credentials = Cred
Try any of these:
Dim Cred As New System.Net.NetworkCredential("user", "password", "domain")
Dim Cred As New System.Net.NetworkCredential("user", "password")
Whats the actual error message?
EDIT:
This seems to be working:
myService.Credentials = Cred
I have a server application that needs to read all calendar entries of user calendars. Users have already authorized and i've stored the authcode and refresh token in my server database. Can i initialize a calendar api v3 calendarservice with the oauth2 token that i have saved? i can't figure out how to get it work without asking for user authorization at run time.
i have this working, but i can't determine how to inialize the service with a predefined token.
Dim myscopes As String() = New String() {CalendarService.Scope.Calendar} ' New () {CalendarService.Scope.Calendar}
Dim secrets As New ClientSecrets() With { _
.ClientId = rs.OAuth2Parameters.ClientId, _
.ClientSecret = rs.OAuth2Parameters.ClientSecret _
}
Dim credential As UserCredential = GoogleWebAuthorizationBroker.AuthorizeAsync(secrets, myscopes, "sellggltest1#gmail.com", System.Threading.CancellationToken.None).Result
Dim service = New CalendarService(New BaseClientService.Initializer() With { _
.HttpClientInitializer = credential, _
.ApplicationName = rs.Application _
})
Dim request As CalendarListResource.ListRequest = service.CalendarList.List()
Dim events As Data.CalendarList = request.Execute()