Skip to content
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

Input 2FA token to spaceauth "automatically"? #14249

Open
gholias opened this Issue Feb 15, 2019 · 16 comments

Comments

Projects
None yet
5 participants
@gholias
Copy link

gholias commented Feb 15, 2019

Feature Request

Motivation Behind Feature

Apple recently announced that Two-Factor Authentication will be required for all developer accounts after 02/27/2019

In an effort to keep your account more secure, two-factor authentication will be required to sign in to your Apple Developer account and Certificates, Identifiers & Profiles starting February 27, 2019. This extra layer of security for your Apple ID helps ensure that you're the only person who can access your account. If you haven't already enabled two-factor authentication for your Apple ID

The goal of this feature request is to give spaceauth extra functionality to allow automated authentication using 2FA.

There is a discussion about the problem at issue #14239

Feature Description

My proposal is that we break down spaceauth in two steps:

  1. The first step would try to login with Apple and generate a request for 2FA code. Something like
    fastlane spaceauth -u user@email.com -p password --requestOnly
    The Apple server will send the code a Text Messate to the phone number that is monitored by my server and put the code value in a ENV VAR called FASTLANE_2FA_CODE
  2. The second step would be run the spaceauth with a parameter to avoid login again and instead just try to enter the 2FA code in the ENV VAR. Something like:
    fastlane spaceauth -u user@email.com --2FACodeOnly

This is the full example of how I would use it:

> fastlane spaceauth -u user@email.com -p password --requestOnly
   fastlane sent the authentication request to Apple. You should receive a Text Message with the code soon.
> sh my_custom_text_number_scanner.sh
   Waiting for Text Messages... 
   Text Message found with 2FA Code... Code 5BT4D was exported to ENV VAR FASTLANE_2FA_CODE
> fastlane spaceauth -u user@email.com --2FACodeOnly
   Fastlane found FASTLANE_2FA_CODE ENV VAR with the code, 5BT4D using it instead of asking the user input
   Fastlane created the session with id XXXXX

Since this would be new parameters to the spaceauth, I don't think it would affect the users that wont need to use it.

Pinging @janpio

@janpio

This comment has been minimized.

Copy link
Collaborator

janpio commented Feb 15, 2019

Thanks, there were some previous discussions on similar features using the 2FA SMS functionality that is now properly implemented in spaceship. I will have to spend some time to find those for context here.

In general, everything making the 2FA process more stable and scalable is welcome.

@levibostian

This comment has been minimized.

Copy link

levibostian commented Feb 15, 2019

@gholias, is this issue trying to address CI servers as well? I cannot tell from the discussion.

@janpio

This comment has been minimized.

Copy link
Collaborator

janpio commented Feb 15, 2019

It is important to note that fastlane already does fully support 2FA for CI @levibostian: https://docs.fastlane.tools/best-practices/continuous-integration/#use-of-application-specific-passwords-and-spaceauth

This issue is just trying to optimize the workflow a bit and make additional automations possible.

@janpio

This comment has been minimized.

Copy link
Collaborator

janpio commented Feb 15, 2019

@gholias How would you implement the my_custom_text_number_scanner.sh?

@gholias

This comment has been minimized.

Copy link
Author

gholias commented Feb 15, 2019

@janpio my first idea is to use a service like Twilio (https://www.twilio.com/sms) to receive the SMS messages and store it in a database. A rest API will consume that database and return the code for a number.
My custom my_custom_text_number_scanner.sh would try to get the code from that REST API every 2 seconds in a loop that will end when the code is fetched from the API or too many tries has passed.

@janpio

This comment has been minimized.

Copy link
Collaborator

janpio commented Feb 15, 2019

Hmm, crazy idea:

We might implement the looping etc in ruby/fastlane, and add a parameter for a polling URL (which expects a specific behavior, e.g. 503 if no token is available, 200 and token in body if it is). Then the user only has to offer that polling endpoint, and not write the polling itself. And we can keep the logic all in the normal login process instead of splitting it in two.

For Twilio (and other standard providers) we could even offer a ready made project that is easy to install on e.g. a free Heroku dyno.

Did I understand Twilio's pricing correctly that for US numbers it is $ 1.00 / month + $ 0.0075 / sms received?

Does this all make sense?

@janpio

This comment has been minimized.

Copy link
Collaborator

janpio commented Feb 15, 2019

(A thing I noticed while thinking about this: Currently you do not automatically get the token via SMS, you have to exit from the normal 2FA flow by entering "sms", then select the wanted trusted phone number. To be able to implement what I suggested above, we have to also change that flow, e.g. also supply the phone number that should automatically be selected to trigger the SMS send. [We also have a few issues about this idea lying around already])

@gholias

This comment has been minimized.

Copy link
Author

gholias commented Feb 15, 2019

@janpio It does make a lot of sense to me, that was my original idea, but breaking in two steps would make this whole process more flexible. But using one step would be perfect

@janpio

This comment has been minimized.

Copy link
Collaborator

janpio commented Feb 15, 2019

What could/would this flexibility be used for? Maybe I am not seeing the big picture yet.

@levibostian

This comment has been minimized.

Copy link

levibostian commented Feb 15, 2019

If you don't mind me sharing a use case: I am a freelancer/indie app dev that maintains a dozen apps at a time with a half a dozen separate Apple developer accounts.

I like fastlane to login to each individual Apple developer account for running tasks instead of adding 1 email address as a role in all dozen of the developer accounts and having fastlane login to that 1 email address for running tasks. I prefer this for security reasons. If I give 1 app access to my fastlane match login information, you get access to all of the apps that are not yours.

Long story short, I have looked into Twilio as a solution for this problem myself. Making it easier for me to login to the browser at least to maintain 1 of the half a dozen developer accounts. This is information I found during my research:

  • Twilio does charge $1 per month for each phone number even if you do not use that phone number at all that month.

  • Apple does not allow you to add 1 phone number to more then 1 developer account at a time.

  • What if you need to allow a human (client, marketing, developer coworker) to login also? You could write Twilio code that forwards the SMS to a team of people's phone numbers if no one has called the endpoint in 30 seconds since the SMS code is received?

I may represent a small number of use cases (maintaining multiple separate developer accounts) but I feel it's worth thinking about.


Could this be built as an optional fastlane plugin if it's a complex add-on for others to use? Could it be built to be compatible with more SMS services such as AWS SNS or others?

I am willing to install a separate service on Heroku, a docker container, etc. if it means that I can automate fastlane on my CI server. Fastlane has done this in the past with other services.

@janpio

This comment has been minimized.

Copy link
Collaborator

janpio commented Feb 15, 2019

Apple does not allow you to add 1 phone number to more then 1 developer account at a time.

Are you 100% sure of that? I just got told you can use the same number for different accounts yesterday.

What if you need to allow a human (client, marketing, developer coworker) to login also? You could write Twilio code that forwards the SMS to a team of people's phone numbers if no one has called the endpoint in 30 seconds since the SMS code is received?

You can also add trusted devices that get a push notification (standard 2FA flow) or another verified phone number that you can select on logging in.

Could this be built as an optional fastlane plugin if it's a complex add-on for others to use?

Not really as a plugin, but maybe as simple configuration options for spaceauth.

We are hooking into the authentication code here, so fastlane (or better spaceship) has to provide at least the logic to: 1. escape/skip the 2FA push token input via parameter, 2. choose a phone number via parameter, 3. execute some code after selecting the phone number (so the polling can be executed somehow) via parameter that replaces the input of the 2FA code.

Could it be built to be compatible with more SMS services such as AWS SNS or others?

Yes, that would be a fully server side thing. By not implementing any "get token from sms" logic into fastlane itself, we are fully flexible here. You could even write your endpoint in a way so that it will only return a value after you manually typed the token into a form. (Which of course defeats the purpose).

I am willing to install a separate service on Heroku, a docker container, etc. if it means that I can automate fastlane on my CI server. Fastlane has done this in the past with other services.

it might be possible to provide a shared service for this, where you create an account, input your twilio/SNS/... API key and then get the endpoint to put into your fastlane configuration. Then at least the server might have a little bit of work to do ;)

@janpio janpio changed the title New features to spaceauth to support 2FA Input 2FA token to spaceauth "automatically"? Feb 15, 2019

@janpio

This comment has been minimized.

Copy link
Collaborator

janpio commented Feb 16, 2019

After sleeping on this idea a bit, I realized this could be even bigger and more impactful:

Until now we were talking about how to make spaceauth more convenient. But then you still have to set the returned value as a environment variable, and repeat this process when the session times out.

If this really works and is stable, we could also add it to the normal login process and thus fully automating 2FA handling again. It could create normal login sessions by automating the retrieval of 2FA tokens and just re-do that login when the session gets invalidated.


I looked at the fastlane\spaceship\lib\spaceship\two_step_or_factor_client.rb code, and it would actually be not too hard to implement - most of the building blocks are already there.

Instead of introducing any new parameters as suggested above, it would probably be better to do it via ENV variables. 2FA_TOKEN_RETRIEVAL_ENDPOINT for the http endpoint to get the token, and 2FA_TOKEN_RETRIEVAL_PHONE_NO for the phone number to automatically select to send the code to could work.

The only thing that really has to be written from scratch is a) some logic that does the polling of that endpoint (although we already have polling for builds or retry of requests, so I can probably get inspiration there) and b) the endpoint itself, that can be hosted somewhere for free/cheap and integrate with any SMS providers.


Super crazy idea: If I remember correctly there was a way to access SMS on Android from an app. (You can't get those into Play Store easily any more, but on development devices should be fine). Theoretically it should be possible to build an app that listens for 2FA SMS and sends those to an API. Stored there, this could be the source for the endpoint we talked above. Then you don't need any Twilio account that incurs cost - just an old Android phone with a prepaid SIM that sits somewhere plugged into power so it can always receive SMS.


Does this make sense?

@janpio

This comment has been minimized.

Copy link
Collaborator

janpio commented Feb 16, 2019

After thinking about it some more, this can indeed be implemented as a fastlane plugin. It also should be implemented as such, as this is far out of core fastlane core area. The plugin would effectively ensure that there is always a valid session available for fastlane and spaceship to use, thus making manual entry or management of the session cookie obsolete.

The server side component could theoretically also be used via a shared installation, as each user has a "secret": the phone number. (If more security is wanted, we can either implement a registration system - or just offer the code for individual hosting/installation in private installations).

The Android app on the other hand looks more like a very hacky, but "free" solution (which developer doesn't have a few older Android devices lieing around?) that doesn't require the server setup and the SMS provider account. Should be easy enough to build as well (Famous last words).

I'll invest an afternoon to find out if this actually works.

@levibostian

This comment has been minimized.

Copy link

levibostian commented Feb 17, 2019

@janpio Thank you for your thoughts and sharing them. Here are some replies for you.

Apple does not allow you to add 1 phone number to more then 1 developer account at a time.

Are you 100% sure of that? I just got told you can use the same number for different accounts yesterday.

I apologize that before I sent you the comment, I did not double check that this is true. When I was reading up on the potential of doing Twilio 2FA verification 6-12months ago, I could have sworn I read this. However, after quick research now to try and find this information, I cannot. This could easily be verified by trying to do it 😄 on 2 accounts.

What if you need to allow a human (client, marketing, developer coworker) to login also? You could write Twilio code that forwards the SMS to a team of people's phone numbers if no one has called the endpoint in 30 seconds since the SMS code is received?

You can also add trusted devices that get a push notification (standard 2FA flow) or another verified phone number that you can select on logging in.

Very true. This would not work for all of my clients of coworkers as not all of them have iPhones (including me).

As long as this fastlane feature (automating 2FA) is built in a way that a dev could extend it, modify the code, etc then I could add the forwarding functionality in myself to handle my use case.

Super crazy idea: If I remember correctly there was a way to access SMS on Android from an app. (You can't get those into Play Store easily any more, but on development devices should be fine). Theoretically it should be possible to build an app that listens for 2FA SMS and sends those to an API. Stored there, this could be the source for the endpoint we talked above. Then you don't need any Twilio account that incurs cost - just an old Android phone with a prepaid SIM that sits somewhere plugged into power so it can always receive SMS.

Android has made some changes in the past few versions that makes this easier in some ways and harder in others. I recommend using the SMS verification API to do this if an app was a way to solve this problem.

However, because this is for iOS verification, could it be assumed that a lot of people have iPhones instead of Android? If this feature in fastlane was built in a generic enough way, anyone could build a plugin to do this anyway if they wish.

Could this be built as an optional fastlane plugin if it's a complex add-on for others to use?

If this really works and is stable, we could also add it to the normal login process and thus fully automating 2FA handling again. It could create normal login sessions by automating the retrieval of 2FA tokens and just re-do that login when the session gets invalidated.

After thinking about it some more, this can indeed be implemented as a fastlane plugin. It also should be implemented as such, as this is far out of core fastlane core area.

I would agree with your thought process. The core fastlane user is someone who uses fastlane from CLI manually and does not need the automation. Automation takes quite a bit of extra setup but it's not required.

Maybe there is a way to add to the plugin system the ability to hook into the 2FA login process? Built that into fastlane core? When fastlane runs, it checks for a plugin used for 2FA, if none found, it runs the manual process of asking for the code. Plugins can be built for Twilio, AWS SNS, etc automation, Android authentication, etc.

@keehun

This comment has been minimized.

Copy link
Contributor

keehun commented Feb 18, 2019

Although I have nothing of value to add at this particular moment, I just wanted to add my support for this work. @janpio, I really like your idea for the 2FA_TOKEN_RETRIEVAL_ENDPOINT and 2FA_TOKEN_RETRIEVAL_PHONE_NO environment variables. I have to manage over 80 accounts, and this would be a godsend.

@fastlane-bot

This comment has been minimized.

Copy link

fastlane-bot commented Mar 21, 2019

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.

Please make sure to update to the latest fastlane version and check if that solves the issue. Let us know if that works for you by adding a comment 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.