My thoughts about life, startups, and weight lifting.

Author: jpaulynice

Oatfin Selected for Google For Startups Founders Academy

We are super excited to announce that Oatfin will be part of the Google For Startups Founders Academy! At Oatfin, our mission is to enable software engineers to deliver cloud applications faster through self-service automation. We do for software engineers what self-checkout does for retail stores. We enable them to be more agile and remove dependency on platform teams to deliver cloud applications.

The Google For Startup Founders Academy begins on March 3rd and consists of hands-on workshops across a range of topics including customer acquisition, hiring, fundraising, and tech enablement. We are one of 50 high-potential startups that the Google for Startups team selected for the first nationwide cohort. Last year, it was piloted in Atlanta with 45 Georgia based companies.

With Google’s advanced technologies and their sophisticated ecosystem of cutting edge tools, we are excited about how that will help us further our mission. We plan to leverage Google Cloud to further enable developers to deliver cloud applications faster.

Login With Github – Flask/React

While working on Oatfin, one use case we just finished implementing is using Github to allow users to sign up and login for the app. Users can now easily login with Google, Github, and Gitlab.

Our default login is also password-less meaning a user can login with just an email address. We send the login link directly to the email. This adds a layer of security because the user has to have access to the email to login and also validates that the user is a real person. Another problem password-less solves is syncing users from different sign in providers. We can guarantee a user who signed in with Google is the same user from Github or Gitlab.

Our app uses React with Typescript on the front-end and Python, Flask on the back-end. Here is what it looks like.

Part one is to create an OAuth app in Github as explained here.

Part two is setting up the React/Typescript component. When unauthenticated users visit the home page, they are redirected to the login page. That should be your application’s default behavior already.

When users click your ‘Login with Github’ button, they are first sent to Github’s login page with the scopes you want and your client_id like this:


const onClick = async () => {
    window.location.href = 
    'https://github.com/login/oauth/authorize?scope=user:email&client_id=YOUR_CLIENT_ID'
  }

After visiting Github’s website and they login, Github redirects back to your call back page which might still be the login page in our case. In your callback url, there is a now parameter ?code=some_code_text.

Your goal now is to take the code returned from Github and pass it to the Python/Flask app. My login component looks like this:


const Login: React.FC<{}> = () => {
    // ...
  useEffect(() => {
    // see if code was returned, returns an error if the user denies the request
    const newUrl = window.location.href;
    const hasCode = newUrl.includes('?code=');

    if (hasCode) {
      // get the code value
      const url = newUrl.split('?code=')[1].split('#/login');
      const data = {
        code: url[0],
      };
      // send the code to the backend
      submitGithub(data as LoginParamsType);
    }
  }, [submitGithub]);


  const onClick = async () => {
    window.location.href = 
    'https://github.com/login/oauth/authorize?scope=user:email&client_id=YOUR_CLIENT_ID'
  }

    return (
          <Button onClick={onClick} 
            Continue with Github
          </Button>
    )
}

Here we take the code and call the API, which returns access token to store in localStorage.


const submitGithub = async (values: LoginParamsType) => {
    try {
      const res = await accountLogin({ ...values });
      if (res !== undefined && res.access_token !== undefined) {
        window.localStorage.setItem('oatfin_access_token', res.access_token);
    } catch (error) {
      message.error('Unable to login with Github.');
    }
  };

Part three is the Python/Flask login API. We make 2 calls to Github: first to exchange the code we got from the front-end with an access token, then to use the access token to get the user details.


import requests

@api.route('/login', methods=['POST'])
def login():

    req_data = flask.request.get_json()
    code = req_data.get('code')

    if code:
        data = {
                'client_id': app_config.GITHUB_CLIENT_ID,
                'client_secret': app_config.GITHUB_CLIENT_SECRET,
                'code': code
            }
        # exchange the 'code' for an access token
        res = requests.post(
            url='https://github.com/login/oauth/access_token',
            data=data,
            headers={'Accept': 'application/json'}
        )

        if res.status_code != 200:
            raise UnauthenticatedError()

        res_json = res.json()
        access_token = res_json['access_token']

        # get the user details using the access token
        res = requests.get(
            url='https://api.github.com/user',
            headers={
                'Accept': 'application/json',
                'Authorization': 'token {}'.format(access_token)
            }
        )
        if res.status_code != 200:
            raise UnauthenticatedError()

        res_json = res.json()

        names = res_json['name'].split()
        first_name = names[0]
        last_name = names[1]
        login = res_json['login'] or res_json['email']
        avatar = res_json['avatar_url']

        # create the user
        user = UserService().create(...)
        access_token = create_access_token(identity=user.json())

    return flask.jsonify(
        access_token=access_token
    ), 200

Bringing The Blog Back

Just getting my blog back up so I can write about things I find interesting! The last few years have been a period of high growth and learning. One of the best things I did was getting off social media in general and instead spending more time in the gym, reading, meditating and learning. I recently tried to resurrect my LinkedIn profile only because otherwise people don’t think I exist.

Today I finished reading the book, “The Instant Millionaire” which I found very interesting. It’s about a young man who despite several disappointments and setbacks, sets out to become a millionaire. He meets an old gardener who gives him the formula to become an instant millionaire.

I also recently read “The Alchemist”, along the same lines. The book is about a shepherd boy who yearns to travel in search of a worldly treasure as extravagant as any ever found. He meets an Alchemist who guides him on his journey.

There are several key messages in these 2 books and perhaps, the most important one as stated in “The Instant Millionaire”, is:

“When the student is ready, the teacher will appear!”

The opposite is also true. If the student isn’t ready, the teacher will never be able to convince the student. Instead, they will become each other’s nemesis. The student has to set out in search of the light and also be in a state of acceptance! It’s worth saying the teacher could be a 5 year old and the student a 60 year old and vice versa. While the acceptance state can start anytime, it can be influenced by involving the subconscious mind. Once the subconscious mind accepts the message, it’s then easily executed by the conscious mind.

This message rings true in just about every walk of life. It’s also the source of every human struggle as illustrated by the story of Jesus in the Bible. When the teacher shows up before the student is ready, it causes a struggle between logic and emotion whereby emotion always wins!

When I set out to become stronger several years ago, I had no clue what I was doing in the gym, but I was “lifting.” Should someone tell me I was doing something wrong, I would be pissed at them! It’s only recently that I learned to lift properly having picked up the book, “Starting Strength”.

Back to the lessons in these books, the most important message is:

“Financial prosperity and a fulfilling life are goals we can all achieve if we understand the principles of success!”

I just started reading “Choose Yourself!” I’m hoping to write more about these books. Hopefully soon! Cheers!

© 2022 Jay Paulynice