-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Overcome two factor authentication #8
Comments
Thanks for the suggested enhancement 😊 Am I understanding correctly you're trying to figure out how to overcome the two-factor authentication with IBeam? |
yeah, I tried all the way but I am still unable to use my cash account on the container. can you suggest to me how can I use my main account with that? Also, I am willing to put effort into it to make the two-factor auth possible somehow using the IBKR app. Please help me know if there's something I missed out on. |
Right, I see. Unfortunately, IBeam does not handle 2FA automatically, therefore if this is what's stopping the authentication on your cash account then there is nothing that can currently be done by default. You'd need to complete the 2FA each time using your 2FA method or find another method to complete it automatically. If however it isn't the 2FA then I'd suggest you check that you don't have any other places - such as TWS or web services - where you use the cash account credentials. Could you share the IBeam output log in case there's something there that could indicate the problem? Please run it with |
I have solved this problem, contact me to help you out. |
that sounds great. |
hey @jembl super cool you found a way around it! Could I ask you to share your solution here so others can use your findings in the future too? Thanks! 😊 |
yes, so here is how I did it:
and the code to get SMS from storage: Hope this helps, ask me if you have any questions! |
That is fantastic @jembl! 👏 Thank you so much for following up with such a detailed explanation! I was hypothesising that such an approach would be doable but I haven't looked that direction yet. Super happy to see this method worked for you and seriously congrats on devising it on your own! Hey would you be interested in contributing some of these changes to IBeam? So that conditionally IBeam could be set to download the code from a URL (or some other way) and paste it to the login page. This way IBeam's users would only need to set up the SMS client and a pipeline to store the code. I could help you get this done, although no worries if you're busy or not interested, this answer is already a massive help 😊 |
thank you so much @jembl |
Hey @odssh and @jembl 👋 I've got some good news! There's a new version of IBeam currently in testing that should facilitate implementing this pattern. In this new version you will have an opportunity to set up IBeam in a way that will attempt to pull the 2FA code from an external URL. You can try it out by using the image with tag docker pull voyz/ibeam:0.3.0-rc1 Then when running it, do the following:
Alternatively, if you require full customisation in how you acquire the code you can do the following:
Let me know if you'd have any feedback! 😊 |
Hi, |
Hi @odssh thanks for testing it! Sorry to hear it started breaking after a while. Could you copy the output log over to here so I could give it a go at figuring out what's wrong? Thanks! |
Hi @Voyz , |
That's fantastic @odssh thanks for passing this over and for the explanation! I'm really sorry you hit the lock out from IB - it happened to me too when I was testing this new method. I think it may be a good idea to implement some safety mechanism that will stop IBeam from attempting after a number of times as to prevent the lock-out from happening. As for the output log, I'd have a number of questions:
If you could feed me in on as many details regarding these questions as possible, I should be able to understand what is causing the issue on your end. Appreciate your help in the matter! |
thank you for your quick response @Voyz.
|
Just a quick message - I have edited your last reply as the link you provided contains your authentication credentials. Below is your code with the credentials removed. I suggest you remove this gist as soon as possible as to not leak your credentials. import json
import logging
import os
from pathlib import Path
from typing import Union
import requests
from ibeam.src.two_fa_handlers.two_fa_handler import TwoFaHandler
from datetime import datetime, timezone
from twilio.rest import Client
_LOGGER = logging.getLogger('ibeam.' + Path(__file__).stem)
_EXTERNAL_REQUEST_METHOD = os.environ.get('IBEAM_EXTERNAL_REQUEST_METHOD', 'GET')
"""Method to use by the external request 2FA handler."""
_EXTERNAL_REQUEST_URL = os.environ.get('IBEAM_EXTERNAL_REQUEST_URL')
"""URL to use by the external request 2FA handler."""
_EXTERNAL_REQUEST_TIMEOUT = int(os.environ.get('IBEAM_EXTERNAL_REQUEST_TIMEOUT', 300))
"""URL to use by the external request 2FA handler."""
_EXTERNAL_REQUEST_PARAMS = os.environ.get('IBEAM_EXTERNAL_REQUEST_PARAMS')
"""Params to use by the external request 2FA handler."""
_EXTERNAL_REQUEST_HEADERS = os.environ.get('IBEAM_EXTERNAL_REQUEST_HEADERS')
"""Headers to use by the external request 2FA handler."""
def parse_json(s):
if s is None:
return None
try:
return json.loads(s)
except Exception as e:
_LOGGER.exception(e)
return None
class ExternalRequestTwoFaHandler(TwoFaHandler):
def __init__(self, method: str = None,
url: str = None,
timeout: int = None,
params=None,
headers=None):
self.method = method if method is not None else _EXTERNAL_REQUEST_METHOD
self.url = url if url is not None else _EXTERNAL_REQUEST_URL
self.timeout = timeout if timeout is not None else _EXTERNAL_REQUEST_TIMEOUT
self.params = params if params is not None else parse_json(_EXTERNAL_REQUEST_PARAMS)
self.headers = headers if headers is not None else parse_json(_EXTERNAL_REQUEST_HEADERS)
def get_two_fa_code(self) -> Union[str, None]:
try:
# response = requests.request(method=self.method,
# url=self.url,
# timeout=self.timeout,
# params=self.params,
# headers=self.headers, )
# response.raise_for_status()
# return response.content
return self.twilioAuthToken()
except requests.exceptions.HTTPError as err:
_LOGGER.error(err)
return None
def twilioAuthToken(self):
vCode = None
for i in range(20):
vCode = self.getNewMessage()
if vCode != None:
break
else:
pass
if vCode == None:
_LOGGER.error("Did not receive the authentication code")
print("got it", vCode)
return vCode
def getNewMessage(self):
vcode = None
account_sid = 'ACCOUNT_SID'
auth_token = 'AUTH_TOKEN'
dtf = '%Y-%m-%d %H:%M:%S'
client = Client(account_sid, auth_token)
messages = client.messages.list(
limit=1,
to='PHONE_NUMBER'
)
for record in messages:
message = client.messages(record.sid).fetch()
currentTime = datetime.now().timestamp() # current time in utc
dts = str(message.date_created).split('+')[0]
dtf = '%Y-%m-%d %H:%M:%S'
dtSend = datetime.strptime(dts, dtf).replace(tzinfo = timezone.utc).timestamp() # message send time in utc
if currentTime - dtSend <= 10:
vcode2 = message.body
try:
vcode1 = vcode2.split(':')[1]
vcode = int(vcode1.strip(' '))
except:
vcode = None
print(message.body)
return vcode
def __str__(self):
return f"ExternalRequestTwoFaHandler(method={self.method}, url={self.url}, timeout={self.timeout}, params={self.params}, headers={self.headers})" |
Now, thanks for your answers! That's all very helpful to know 😊
This is due to Gateway's Digging into the code I can recognise a few areas that may cause the issues, leading to the unexpected behaviour we're observing in your logs:
if currentTime - dtSend <= 10:
vcode2 = message.body
if 'Your requested authentication code' not in vcode2 or not vcode2[-6:].isdigit():
_LOGGER.error(f'Unrecognised message body: {vcode2}')
else:
try:
vcode1 = vcode2.split(':')[1]
vcode = int(vcode1.strip(' '))
except Exception as e:
_LOGGER.exception(e)
vcode = None This way we can be more sure that the right messages are being parsed, and that we don't return invalid codes (eg. in your existing code a message that reads Lastly, I suggest you remove the following lines: def __str__(self):
return f"ExternalRequestTwoFaHandler(method={self.method}, url={self.url}, timeout={self.timeout}, params={self.params}, headers={self.headers})" As they are misleading, and replace them with: def __str__(self):
return f"TwilioHandler()" I hope these changes help you ensure the right code is returned. We could certainly introduce some changes on IBeam to make things more robust in case wrong code is returned too many times - I'll try to look into this soon. Let me know how it goes! 👍 |
Hi @Voyz |
Thank you so much @Voyz |
Ah glad to hear that! Sorry I stepped over then! 😅
Right, this may be a tricky one to figure out. It would be helpful to mark messages as 'read' and 'unread' on Twilio side - have a look if this is possible. A rigid 10 seconds limit may be a cause of bugs in the future.
Great, looking forward to it! 😊 |
@odssh I've just released a new version Looking forward to hearing how the improvements worked out for you 👍 |
Thank you for the detailed update @Voyz |
Hi @Voyz |
hey @odssh I'm really sorry to hear about the second lock-out, that must be incredibly annoying and I'm going to try my best to help you avoid it in the future. Thanks for submitting the detailed log too. From that I can conclude the following:
These steps should move us forward towards understanding what is wrong. Once again, I'm really sorry you've run into these issues and I'm hoping we'll mange to get to the bottom of this for the benefit of all users of IBeam. Thanks for your patience in the meantime 👍 |
Hi @Voyz |
hey @odssh thanks for outlining all of that! I'd be interested to see and hear what scheduler for the authenticator would do. Keep us posted on your progress 👍 And thanks for the kind words, I'm happy to be able to support you in your trading 😊 |
thank you for all the help and I will definitely make sure to update you on that scheduler thing. docker run -v /inputs:/srv/inputs --env-file paper.list -d -p 5000:5000 ib_with_ssl I am getting the error on making requests. so when I ran the command curl -X GET "https://localhost:5000/v1/api/one/user" --cacert cacert.pem I am getting this error: curl: (60) SSL certificate problem: self-signed certificate curl failed to verify the legitimacy of the server and therefore could not I followed the exact guide in the page tls |
Sorry to hear that @odssh! Which OS are you calling cURL from? What is the content of your /srv/inputs? |
I am running the whole program on the ubuntu server and running the curl command from the same host on which the container is running. |
That's surprising. Can you try mounting that volume to another docker image and seeing if this time the directory contains the files? |
I have tried to mount the inputs directory multiple times in all the ways possible but still the same error and works only when I give -k tag at the end. Should I try manually importing the files inside the container and then restarting the container? |
So when you mount that directory to another container that uses a different image (not IBeam) you also don't see any files inside of the mounted directory? This would lead me to the following guesses:
The latter two are easier to verify, but if these aren't the cause of the issue then I'm sorry but I'm not entirely sure how to help you. You could try the setup on a different machine with a fresh installation of Docker and see if the issue exists there too? |
root@henon:~/gateway/inputs# curl -X GET "https://localhost:5000/v1/api/one/user" --cacert cacert.pem curl failed to verify the legitimacy of the server and therefore could not That is the error message I am getting now even after copying the ca certificate manually to the destination inside the container. Also, how can I use the default certificate that comes with a gateway with python instead of that custom one. I went with the custom as the default certificate wasn't working with the python |
I don't know how IBeam would behave if you copy the certificates manually - this is an unexpected behaviour and isn't really supported. How about the points I brought up in my previous reply? The default certificate needs to be provided through the Inputs Directory, but since you can't mount the volume correctly this will not be possible until that gets sorted |
root@henon:~/gateway/inputs# curl -X GET "https://localhost:5000/v1/api/one/user" --cacert cacert.pem curl failed to verify the legitimacy of the server and therefore could not Hi, @Voyz |
Okay @odssh, I'm trying to help you but I'm feeling there's some miscommunication between us. I need you to address the points that I bring up. It's useful that you provide me with the error messages, but there's a number of questions or observations I replied you with that you haven't really addressed. Please let's do things in the right order and so we can figure out how to fix your setup, okay? You need to start by discovering what is the reason for not being able to mount the Docker volume correctly. Have a look at this reply I made #8 (comment) and confirm for me which seems to be the case - or update me if this is no longer a problem and you can now mount volumes correctly. Otherwise please provide some screenshots of outputs of |
Hi @Voyz thank you so much for your support. Finally got it to work with the custom SSL certificate. I was providing the wrong path for the input folder and I just kept trying with the same wrong path. |
Hey, happy to hear you got that sorted! Issues with Access Denied are described in the Troubleshooting: https://github.com/Voyz/ibeam/wiki/Troubleshooting#access-denied This should help you out 👍 |
Actually, it's working fine with the endpoint https://localhost:5000/v1/api/one/user but failing with the historical data endpoint. I think this issue is probably because of how I have written my request and have nothing to do with iBeam. Please let me know if there's any other endpoint you have worked with as I think I am providing the conid wrong. Any idea on how can I generate it? |
You can check the conid's here: Just type the symbol, click on 'Details' of the right stock and conid will be there. Paste your full code for performing the request here, including the headers and parameters if you'd like me to see if I can spot something wrong with it. |
Hey @Voyz! I stumbled across your repo as I've been working on a similar project. I've come up with a solution to two factor authentication in case you're interested in another approach. 😄 |
Hey @michaeljherrmann welcome to IBeam mate! 👋 Super cool of you to share your project, fantastic to see your approach! The direct API requests you do are amazing, great job figuring this out! Just out of curiosity - do you know if your API interaction isn't against their TOC? Going with Twilio is something that others have suggested in this thread, how do you find it working out for you? |
Hmm good question about the TOC, not something I've really dug into but you're probably right. I'll look further and perhaps I should rollback what I've publicly published. In terms of Twilio, it works great! I've personally been using it consistently for about 3 months. It was easy to set up and has been pretty smooth overall, twilio had one outage for a few hours but that was it. The caveat with SMS two factor & IB is that they don't let you change the phone number from what the account was registered with. After talking with customer support, they insisted I set up IBKey auth via mobile app instead and that they would not be able to change the phone number, which is what led me down the IBKey route. |
Not sure if it is against TOC - I've had others suggesting doing exactly what you did in other threads. I'd just double check - maybe even ask them directly after having unpublished the code temporarily - if it's good then put it up mate, it's fantastic. Glad to hear Twilio works great for you too! We actually expect such usage with IBeam v0.3.0 too, allowing to communicate with an external server on 2FA request. It does sound annoying they forced you to stick with just one phone number. |
Hi Folks, Basically, you setup a Twilio account and get a phone number and then setup a SMS webhook to https://your-site.com/sms/incoming. Then paste in the following code to your Node.js express web server:
Next, start your docker container using something like: I hope this helps someone... and also, great work Voyz !!!, you have saved a lot of people a lot of time =) |
That's very useful @kashyappatel7 many thanks for sharing this! I'll add a link to this to the 2FA Wiki. And thanks for the kind words, I'm glad to help you find IBeam useful 😊 |
Hi, I tried to use Twilio to receive 2FA codes from IBKR but the 2FA messages don't even show up on Twilio REST API or their website. Apparently this is because virtual numbers cannot send SMS to other virtual numbers (IBKR sends 2FA from a virtual number). Is the Twilio solution still working for anyone? |
@psyfb2 Sorry, I never used Twilio, couldn't comment on that. Google Messages solution works. |
Describe the feature
I am trying to access the API using a cash account but it's not working and giving the login failed message while it's working perfectly fine with a paper account. Can you tell me how can I fix that or if possible can we add that authentication feature?
Expected interaction
Using a two-factor authentication device
Possible implications
Only cash account authentications
Additional context
Please suggest to me if there's any workaround to that
The text was updated successfully, but these errors were encountered: