Category Archives: TUTORIALS

Detailed tutorials explaining how to build most common applications, in different languages.

Different ways to use oAuth in your WebAp

Oauth2 workflow:

1. Authorization Request

  • User clicks the Log-In link:
    `<a href="https://toninichev.com/examples/oauth/oauth-service/sign-in.php?site=siteone&page=index.html">Log-In</a>`

    This link redirects the user to the authorization server:

    https://toninichev.com/examples/oauth/oauth-service/sign-in.php?site=siteone&page=index.html

    with query parameters indicating the target application and redirect page.


2. Authorization Grant

  • The sign-in.php script initiates the OAuth2 process:
    • Redirects the user to the OAuth provider (e.g., Google, Facebook).
    • Handles scopes and client credentials as per the provider’s requirements.

3. Token Exchange

  • After successful authorization by the user:
    • The OAuth provider redirects the user back to the callback.php or callback-google.php scripts, including an authorization code (or token) in the query string.example: https://toninichev.com/examples/oauth/oauth-service/callbacks/callback.php?provider=google&state=123&code=4%2F0AanRRruVnGL8TtqeJoQOuaQSPCW1lOGHA2Y15m_uva9M8Cj75Tb08Y81pPW2H147acXRaA&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&authuser=0&prompt=none
    • The scripts exchange the authorization code for an access token, typically using the POST method with the client secret.

4. Returning to the Application

 

  • The token is returned to the frontend:
    • Via query parameters in the URL after the server-side processing.
    • Example: https://public.toni-develops.com/examples/oauth2/site-one/index.html?token=xxxxxxx&email=XXXXXX

5. Managing User Sessions

  • The script.js handles the query parameters on the frontend:
    • initOnLoad extracts token and user information.
    • setCookie stores user data securely in the browser for session continuity.
    • setUserLoggedIn updates the UI to reflect the user’s logged-in state.

6. Token Usage

  • The token (JWT) is used to:
    • Authenticate subsequent API calls.
    • Validate the user’s session on subsequent visits.

7. Logout

  • The logOutUser function clears the user session and cookie data:
    user = null;
    setCookie('user', null, 2);

Additional Features

  • Pop-up Login Option: The showModalPopUp function demonstrates an alternative way to display the OAuth provider’s login page.
  • Message Passing: receiveMessage listens for user data sent from the OAuth popup.

Future improvements and considerations:

  1. Secure Cookie Handling:
    • Use Secure and HttpOnly flags for cookies to prevent XSS and CSRF.
  2. Token Expiry:
    • Ensure the access token has an expiration mechanism.
    • Include token refresh logic to maintain seamless user sessions.
  3. Redirect URL Validation:
    • Ensure the redirect URLs (site and page parameters) are validated server-side to avoid open redirect vulnerabilities.
  4. CSRF Protection:
    • Use state parameters to mitigate CSRF attacks during the OAuth2 flow.

 

For the simplicity of this example we are not going to add this but it’s good to mention, and mandatory in production apps.

 

Example1: Using full redirect

This way after clicking on log-in button user is redirected to the sign-in page with all sign-in providers to choose from. Clicking on “continue with …” redirects to provider’s web ui and then redirects back to out web app.

Example2: Using new popup-browser window

This will open popup window form different domain, will handle the authentication and will use window messaging to send back the user token and data.

 Example3:Using iframe

Same as the Example2 but using idrame instead pop-up.

Zigzag Conversion

Task

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R

And then read line by line: "PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

Example 1:

Input:

 s = "PAYPALISHIRING", numRows = 3

Output:

 "PAHNAPLSIIGYIR"

Example 2:

Input:

 s = "PAYPALISHIRING", numRows = 4

Output:

 "PINALSIGYAHRPI"

Explanation:

P     I    N
A   L S  I G
Y A   H R
P     I

Example 3:

Input:

 s = "A", numRows = 1

Output:

 "A"

 

This problem was taken from Leet code, ZigZag conversion

 

Solution

Log In With Apple using redirect pop-up

This tutorial demonstrates how to use oAuth to sign-in with Apple without using any library.We simply use HTTP GET request to their endpoint URL: appleid.apple.com/auth/authorize.

Just to space it up a bit, we are opening Sign-in popup in modal window using window.open but this could be done in the same window. The advantages of open it in modal window are that the user won’t be redirect to different screens and got confused of what’s going on.

Full example here

Main Web app

index.html

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<html>
<head>
<style>
</style>
<script type = "text/javascript">
var popUpObj;
function showModalPopUp()
{
popUpObj=window.open(
"log-in-popup.html",
"ModalPopUp",
"toolbar=no," +
"scrollbars=no," +
"location=no," +
"statusbar=no," +
"menubar=no," +
"resizable=0," +
"width=500," +
"height=640," +
"left = 480," +
"top=300"
);
popUpObj.focus();
}
function receiveUserSignedInData(parsedToken) {
console.dir(parsedToken, { depth: null });
}
</script>
</head>
<body>
<h1>Welcome to oAuth example</h1>
<input id="Button1" type="button" value="Log In" onclick="showModalPopUp()">
</body>
</html>
<html> <head> <style> </style> <script type = "text/javascript"> var popUpObj; function showModalPopUp() { popUpObj=window.open( "log-in-popup.html", "ModalPopUp", "toolbar=no," + "scrollbars=no," + "location=no," + "statusbar=no," + "menubar=no," + "resizable=0," + "width=500," + "height=640," + "left = 480," + "top=300" ); popUpObj.focus(); } function receiveUserSignedInData(parsedToken) { console.dir(parsedToken, { depth: null }); } </script> </head> <body> <h1>Welcome to oAuth example</h1> <input id="Button1" type="button" value="Log In" onclick="showModalPopUp()"> </body> </html>
<html>
    <head>
      <style>

      </style>

    <script type = "text/javascript">

      var popUpObj;

      function showModalPopUp()    
      {
      popUpObj=window.open(
        "log-in-popup.html",
        "ModalPopUp",
        "toolbar=no," +
        "scrollbars=no," +
        "location=no," +
        "statusbar=no," +
        "menubar=no," +
        "resizable=0," +
        "width=500," +
        "height=640," +
        "left = 480," +
        "top=300"
      );

      popUpObj.focus();
      }   

      function receiveUserSignedInData(parsedToken) {
        console.dir(parsedToken, { depth: null });
      }

    </script>
    </head>
    <body>
    <h1>Welcome to oAuth example</h1>
    <input id="Button1" type="button" value="Log In" onclick="showModalPopUp()">
    </body>
</html>

The main app simply has a button that opens modal window with sign-in button. Line 39.

Log-In popup window

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<html>
<head>
<style>
#apple-auth-button {
webkit-box-align: baseline;
align-items: baseline;
border-width: 0px;
border-radius: 3px;
box-sizing: border-box;
display: inline-flex;
font-size: inherit;
font-style: normal;
font-family: inherit;
max-width: 100%;
position: relative;
text-align: center;
text-decoration: none;
transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s;
white-space: nowrap;
cursor: pointer;
padding: 0px 10px;
vertical-align: middle;
width: 100%;
-webkit-box-pack: center;
justify-content: center;
font-weight: bold;
color: var(--ds-text,#42526E) !important;
height: 40px !important;
line-height: 40px !important;
background: rgb(255, 255, 255) !important;
box-shadow: rgb(0 0 0 / 20%) 1px 1px 5px 0px !important
}
</style>
</head>
<body>
<a href="https://appleid.apple.com/auth/authorize?client_id=com.sign-in-with-apple-example-redirect-service&redirect_uri=https://www.toni-develops.com/external-files/examples/oauth-with-apple-with-redirect-step-by-step/callback.php&response_type=code id_token&state=123&scope=name email&response_mode=form_post">Sign In with Apple Simple A tag</a>
<hr/>
<div id="signInPanel">
<form action="https://appleid.apple.com/auth/authorize?" method="get">
<input type="hidden" id="client_id" name="client_id" value="com.sign-in-with-apple-example-redirect-service" />
<input type="hidden" id="redirect_uri" name="redirect_uri" value="https://www.toni-develops.com/external-files/examples/oauth-with-apple-with-redirect-step-by-step/callback.php" />
<input type="hidden" id="response_type" name="response_type" value="code id_token"/>
<input type="hidden" id="scope" name="scope" value="name email" />
<input type="hidden" id="response_mode" name="response_mode" value="form_post" />
<button id="apple-auth-button" class="css-11s2kpt" type="submit" tabindex="0">
<span class="css-1ujqpe8">
<img class="appleLogo" src="https://www.toni-develops.com/external-files/examples/assets/apple-logo.svg" alt="">
</span>
<span class="css-19r5em7"><span>Continue with Apple</span>
</button>
</form>
</div>
</body>
</html>
<html> <head> <style> #apple-auth-button { webkit-box-align: baseline; align-items: baseline; border-width: 0px; border-radius: 3px; box-sizing: border-box; display: inline-flex; font-size: inherit; font-style: normal; font-family: inherit; max-width: 100%; position: relative; text-align: center; text-decoration: none; transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s; white-space: nowrap; cursor: pointer; padding: 0px 10px; vertical-align: middle; width: 100%; -webkit-box-pack: center; justify-content: center; font-weight: bold; color: var(--ds-text,#42526E) !important; height: 40px !important; line-height: 40px !important; background: rgb(255, 255, 255) !important; box-shadow: rgb(0 0 0 / 20%) 1px 1px 5px 0px !important } </style> </head> <body> <a href="https://appleid.apple.com/auth/authorize?client_id=com.sign-in-with-apple-example-redirect-service&redirect_uri=https://www.toni-develops.com/external-files/examples/oauth-with-apple-with-redirect-step-by-step/callback.php&response_type=code id_token&state=123&scope=name email&response_mode=form_post">Sign In with Apple Simple A tag</a> <hr/> <div id="signInPanel"> <form action="https://appleid.apple.com/auth/authorize?" method="get"> <input type="hidden" id="client_id" name="client_id" value="com.sign-in-with-apple-example-redirect-service" /> <input type="hidden" id="redirect_uri" name="redirect_uri" value="https://www.toni-develops.com/external-files/examples/oauth-with-apple-with-redirect-step-by-step/callback.php" /> <input type="hidden" id="response_type" name="response_type" value="code id_token"/> <input type="hidden" id="scope" name="scope" value="name email" /> <input type="hidden" id="response_mode" name="response_mode" value="form_post" /> <button id="apple-auth-button" class="css-11s2kpt" type="submit" tabindex="0"> <span class="css-1ujqpe8"> <img class="appleLogo" src="https://www.toni-develops.com/external-files/examples/assets/apple-logo.svg" alt=""> </span> <span class="css-19r5em7"><span>Continue with Apple</span> </button> </form> </div> </body> </html>
<html>
    <head>
        <style>
            #apple-auth-button {
                webkit-box-align: baseline;
                align-items: baseline;
                border-width: 0px;
                border-radius: 3px;
                box-sizing: border-box;
                display: inline-flex;
                font-size: inherit;
                font-style: normal;
                font-family: inherit;
                max-width: 100%;
                position: relative;
                text-align: center;
                text-decoration: none;
                transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s;
                white-space: nowrap;
                cursor: pointer;
                padding: 0px 10px;
                vertical-align: middle;
                width: 100%;
                -webkit-box-pack: center;
                justify-content: center;
                font-weight: bold;
                color: var(--ds-text,#42526E) !important;
                height: 40px !important;
                line-height: 40px !important;
                background: rgb(255, 255, 255) !important;
                box-shadow:  rgb(0 0 0 / 20%) 1px 1px 5px 0px !important           
            }
        </style>

    </head>
    <body>
        <a href="https://appleid.apple.com/auth/authorize?client_id=com.sign-in-with-apple-example-redirect-service&redirect_uri=https://www.toni-develops.com/external-files/examples/oauth-with-apple-with-redirect-step-by-step/callback.php&response_type=code id_token&state=123&scope=name email&response_mode=form_post">Sign In with Apple Simple A tag</a>

        <hr/>

        <div id="signInPanel">
            
            <form action="https://appleid.apple.com/auth/authorize?" method="get">
                <input type="hidden" id="client_id" name="client_id" value="com.sign-in-with-apple-example-redirect-service" />
                <input type="hidden" id="redirect_uri" name="redirect_uri" value="https://www.toni-develops.com/external-files/examples/oauth-with-apple-with-redirect-step-by-step/callback.php" />
                <input type="hidden" id="response_type" name="response_type" value="code id_token"/>
                <input type="hidden" id="scope" name="scope" value="name email" />
                <input type="hidden" id="response_mode" name="response_mode" value="form_post" />

                <button id="apple-auth-button" class="css-11s2kpt" type="submit" tabindex="0">
                <span class="css-1ujqpe8">
                    <img class="appleLogo" src="https://www.toni-develops.com/external-files/examples/assets/apple-logo.svg" alt="">
                </span>
                <span class="css-19r5em7"><span>Continue with Apple</span>
                </button> 
            </form>

          </div>        
    </body>
</html>

This window create two sign-in entities: one is simple A tag that demonstrates how we could start sign-in redirect process by simply redirect browser to authentication service, and the second one is a button, that does the same using form submit.

Callback function

callback.php

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<html>
<head>
<style>
</style>
<script type = "text/javascript">
var id_token = "<?php echo $_POST['id_token'] ?>";
function parseJwt (token) {
var base64Url = token.split('.')[1];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
}
function sendDataToMainApp() {
var parsedToken = parseJwt(id_token);
window.opener.receiveUserSignedInData(parsedToken);
window.close();
}
</script>
</head>
<body onLoad="sendDataToMainApp()">
</body>
</html>
<html> <head> <style> </style> <script type = "text/javascript"> var id_token = "<?php echo $_POST['id_token'] ?>"; function parseJwt (token) { var base64Url = token.split('.')[1]; var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); return JSON.parse(jsonPayload); } function sendDataToMainApp() { var parsedToken = parseJwt(id_token); window.opener.receiveUserSignedInData(parsedToken); window.close(); } </script> </head> <body onLoad="sendDataToMainApp()"> </body> </html>
<html>
    <head>
      <style>

      </style>
      <script type = "text/javascript">
        var id_token = "<?php echo $_POST['id_token'] ?>";


        function parseJwt (token) {
          var base64Url = token.split('.')[1];
          var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
          var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
              return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
          }).join(''));

          return JSON.parse(jsonPayload);
        }           

        function sendDataToMainApp() {
          var parsedToken = parseJwt(id_token);
          window.opener.receiveUserSignedInData(parsedToken);
          window.close();
        }
      </script>
    </head>
    <body onLoad="sendDataToMainApp()">

    
    
    </body>
</html>

what we just did:

Were, we get id_token from Apple authentication service, that passes this via the request type that we selected (post, fragment, get) decodes, id_token then passes it to the parent window and closes itself.

 

Full example here

 

Using Oauth2 to sign-in users with Apple using Java Script Library

Example project here

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<html>
<head>
<style>
h1 {
text-align: center;
}
#welcomePanel {
display: none;
text-align: center;
}
#signInPanel h2 {
text-align: center;
border: 1px solid silver;
}
#google-auth-button {
-webkit-box-align: baseline;
align-items: baseline;
border-width: 0px;
border-radius: 3px;
box-sizing: border-box;
display: inline-flex;
font-size: inherit;
font-style: normal;
font-family: inherit;
max-width: 100%;
position: relative;
text-align: center;
text-decoration: none;
transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s;
white-space: nowrap;
cursor: pointer;
padding: 0px 10px;
vertical-align: middle;
width: 100%;
-webkit-box-pack: center;
justify-content: center;
font-weight: bold;
color: var(--ds-text,#42526E) !important;
height: 40px !important;
line-height: 40px !important;
background: rgb(255, 255, 255) !important;
box-shadow: rgb(0 0 0 / 20%) 1px 1px 5px 0px !important;
}
</style>
<!-- First we have to include Apple Sign-in script -->
<script
type="text/javascript"
src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
</head>
<body>
<script>
function parseJwt (token) {
var base64Url = token.split('.')[1];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
}
/**
* This function will initialize the `AppleID.auth` object with parameter we pass in.
*/
const initApple = () => {
window.AppleID.auth.init({
clientId: "com.toni-develops.sign-in-with-apple-identifier", // This is the service ID we created.
scope: "name email", // To tell apple we want the user name and emails fields in the response it sends us.
redirectURI: "https://www.toni-develops.com/external-files/examples/oauth-with-apple-using-js-library", // As registered along with our service ID
state: "origin:web", // Any string of your choice that you may use for some logic. It's optional and you may omit it.
usePopup: true, // Important if we want to capture the data apple sends on the client side.
});
};
/**
* This function is where the magic happens.
* This is a simple example, ideally you'll have catch block as well to handle authentication failure.
*/
const singInApple = async () => {
const response = await window.AppleID.auth.signIn();
return response;
};
initApple();
function signInWithApple() {
const userData = singInApple();
userData.then( (data) => {
console.dir(data, { depth: null });
const result = parseJwt(data.authorization.id_token)
console.dir(result, { depth: null });
document.querySelector('#signInPanel').innerHTML = '<h2>Welcome ' + result.email + '</h2>';
});
}
</script>
<h1>Sign-In with Apple using Java Script library example</h1>
<div id="signInPanel">
<button id="google-auth-button" class="css-11s2kpt" type="button" tabindex="0" onclick="signInWithApple()">
<span class="css-1ujqpe8">
<img class="appleLogo" src="https://www.toni-develops.com/external-files/examples/assets/apple-logo.svg" alt="">
</span>
<span class="css-19r5em7"><span>Continue with Apple</span>
</button>
</div>
</body>
</html>
<html> <head> <style> h1 { text-align: center; } #welcomePanel { display: none; text-align: center; } #signInPanel h2 { text-align: center; border: 1px solid silver; } #google-auth-button { -webkit-box-align: baseline; align-items: baseline; border-width: 0px; border-radius: 3px; box-sizing: border-box; display: inline-flex; font-size: inherit; font-style: normal; font-family: inherit; max-width: 100%; position: relative; text-align: center; text-decoration: none; transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s; white-space: nowrap; cursor: pointer; padding: 0px 10px; vertical-align: middle; width: 100%; -webkit-box-pack: center; justify-content: center; font-weight: bold; color: var(--ds-text,#42526E) !important; height: 40px !important; line-height: 40px !important; background: rgb(255, 255, 255) !important; box-shadow: rgb(0 0 0 / 20%) 1px 1px 5px 0px !important; } </style> <!-- First we have to include Apple Sign-in script --> <script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script> </head> <body> <script> function parseJwt (token) { var base64Url = token.split('.')[1]; var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); return JSON.parse(jsonPayload); } /** * This function will initialize the `AppleID.auth` object with parameter we pass in. */ const initApple = () => { window.AppleID.auth.init({ clientId: "com.toni-develops.sign-in-with-apple-identifier", // This is the service ID we created. scope: "name email", // To tell apple we want the user name and emails fields in the response it sends us. redirectURI: "https://www.toni-develops.com/external-files/examples/oauth-with-apple-using-js-library", // As registered along with our service ID state: "origin:web", // Any string of your choice that you may use for some logic. It's optional and you may omit it. usePopup: true, // Important if we want to capture the data apple sends on the client side. }); }; /** * This function is where the magic happens. * This is a simple example, ideally you'll have catch block as well to handle authentication failure. */ const singInApple = async () => { const response = await window.AppleID.auth.signIn(); return response; }; initApple(); function signInWithApple() { const userData = singInApple(); userData.then( (data) => { console.dir(data, { depth: null }); const result = parseJwt(data.authorization.id_token) console.dir(result, { depth: null }); document.querySelector('#signInPanel').innerHTML = '<h2>Welcome ' + result.email + '</h2>'; }); } </script> <h1>Sign-In with Apple using Java Script library example</h1> <div id="signInPanel"> <button id="google-auth-button" class="css-11s2kpt" type="button" tabindex="0" onclick="signInWithApple()"> <span class="css-1ujqpe8"> <img class="appleLogo" src="https://www.toni-develops.com/external-files/examples/assets/apple-logo.svg" alt=""> </span> <span class="css-19r5em7"><span>Continue with Apple</span> </button> </div> </body> </html>
<html>
    <head>
      <style>
        h1 {
          text-align: center;
        }

        #welcomePanel {
          display: none;
          text-align: center;
        }

        #signInPanel h2 {
          text-align: center;
          border: 1px solid silver;
        }

        #google-auth-button {
          -webkit-box-align: baseline;
          align-items: baseline;
          border-width: 0px;
          border-radius: 3px;
          box-sizing: border-box;
          display: inline-flex;
          font-size: inherit;
          font-style: normal;
          font-family: inherit;
          max-width: 100%;
          position: relative;
          text-align: center;
          text-decoration: none;
          transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s;
          white-space: nowrap;
          cursor: pointer;
          padding: 0px 10px;
          vertical-align: middle;
          width: 100%;
          -webkit-box-pack: center;
          justify-content: center;
          font-weight: bold;
          color: var(--ds-text,#42526E) !important;
          height: 40px !important;
          line-height: 40px !important;
          background: rgb(255, 255, 255) !important;
          box-shadow: rgb(0 0 0 / 20%) 1px 1px 5px 0px !important;
        }
      </style>
      <!-- First we have to include Apple Sign-in script -->
      <script
        type="text/javascript"
        src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
    </head>
    <body>
      <script>

        function parseJwt (token) {
            var base64Url = token.split('.')[1];
            var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
            var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
                return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
            }).join(''));

            return JSON.parse(jsonPayload);
        }

        /**
         * This function will initialize the `AppleID.auth` object with parameter we pass in.
         */
       
        const initApple = () => {
          window.AppleID.auth.init({
            clientId: "com.toni-develops.sign-in-with-apple-identifier", // This is the service ID we created.
            scope: "name email", // To tell apple we want the user name and emails fields in the response it sends us.
            redirectURI: "https://www.toni-develops.com/external-files/examples/oauth-with-apple-using-js-library", // As registered along with our service ID
            state: "origin:web", // Any string of your choice that you may use for some logic. It's optional and you may omit it.
            usePopup: true, // Important if we want to capture the data apple sends on the client side.
          });
        };        
        
        
        /**
         * This function is where the magic happens.
         * This is a simple example, ideally you'll have catch block as well to handle authentication failure.
         */
        const singInApple = async () => {
          const response = await window.AppleID.auth.signIn();

          return response;
        };     
        
        initApple();


        function signInWithApple() {
          const userData = singInApple();

          userData.then( (data) => {
            console.dir(data, { depth: null });
            const result = parseJwt(data.authorization.id_token)
            console.dir(result, { depth: null });

            document.querySelector('#signInPanel').innerHTML = '<h2>Welcome ' + result.email + '</h2>';
          });
        }
      </script>
      <h1>Sign-In with Apple using Java Script library example</h1>
      <div id="signInPanel">
        <button id="google-auth-button" class="css-11s2kpt" type="button" tabindex="0" onclick="signInWithApple()">
          <span class="css-1ujqpe8">
            <img class="appleLogo" src="https://www.toni-develops.com/external-files/examples/assets/apple-logo.svg" alt="">
          </span>
          <span class="css-19r5em7"><span>Continue with Apple</span>
        </button> 
      </div>
    </body>
</html>

 

Sign-in with Apple prerequisite

In order to add Sign-In with Apple we have to do the following:

  1. Create an App ID.
  2. Create a Service ID.
  3. Register the domains for your website.

Create App ID

  • Select App and click continue

  • add description and Bundle ID following reverse domain recommendation by Apple

 

  • confirm and hit register

 

 

Register Service ID

  • Go back to https://developer.apple.com/account/resources/identifiers/add/bundleId
  • this time select “Service ID” and click continue

  • add description and identifier

  • select identifier that you just created

  • check the checkbox to configure the identifier and hit configure

  • add the domain and the Return URLs (Make a note of the return url since we have to add it into our Java Script code later)

.

 

Using oAuth2.0 to sign-in with Google using redirect method

No library required

In this example we have the main app (in this case my blogpost) with a Log-in button (Log in Example, above ), that redirects to the Log-In app, which on the other hand redirects to selected Log-In service (Google, Apple, Facebook, Github) passing app id an all necessary log in data.

After the user grant permissions to share requested data (email, username, real name, etc.) called scope, authentication service is calling back our app service, passing code which our service is using to make HTTP request to the provider and exchange it for JWT (Jason Web Token) containing requested user information.

Create Authorization credentials

  • Navigate to https://console.cloud.google.com/apis/credentials  and click on the + CREATE CREDENTIALS on the top left of the page.
  • on Authorized Java Script Origins add the domain from where the WEB app will be served. You could use http://localhost if you like.
  • on Authorized Redirect URIs add authentication service callback script that Google will call to pass code that could be exchanged for JWT (JSON Web Token) containing user’s information requested.

On the top right corner you will see ClientID and App secret. Write them down since we are going to need them in our authentication service later on.

Create main WEB app and authentication service

We will create main WEB app and authentication service that main app will use. This way same authentication service could be used for different WEB aps.

(Main web app) with Log In button, that redirects to the authentication app.

Let’s get started by creating simple WEB app that will have Log In button, that will simply redirect to our log in service. I already did that in the “Log In Example” above.

index.html

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<html>
<head>
<style>
...
</style>
</head>
<body>
<!-- there is no Java script involved at all -->
<div id="log_in_wrapper">
<button class='continue_with_google'>
<a href='https://log-in-service-app/index.html'>
Log In
</a>
</button>
</div>
</body>
</html>
<html> <head> <style> ... </style> </head> <body> <!-- there is no Java script involved at all --> <div id="log_in_wrapper"> <button class='continue_with_google'> <a href='https://log-in-service-app/index.html'> Log In </a> </button> </div> </body> </html>
<html>
  <head>
    <style>
     ...
    </style>
  </head>

  <body>
    <!-- there is no Java script involved at all -->
    <div id="log_in_wrapper">
      <button class='continue_with_google'>
        <a href='https://log-in-service-app/index.html'>
          Log In
        </a>
      </button>
    </div>
  </body>
</html>

Nothing fancy happens here. We have button that simply redirects to our authentication service, which draws log-in with  buttons (with Google, Apple, Facebook, GitHub)

(Authentication app) that shows log-in with  buttons (with Google, Apple, Facebook, GitHub)

index.php

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<html>
<head>
<style>
...
</style>
</head>
<body>
<!-- there is no Java script involved at all -->
<div id="log_in_wrapper">
<button class='continue_with_google'>
<a href='step-1-auth-google-get-redirect.php'>
<img src="some-google-logo"/>
<span>Continue with Google</span>
</a>
</button>
</div>
</body>
</html>
<html> <head> <style> ... </style> </head> <body> <!-- there is no Java script involved at all --> <div id="log_in_wrapper"> <button class='continue_with_google'> <a href='step-1-auth-google-get-redirect.php'> <img src="some-google-logo"/> <span>Continue with Google</span> </a> </button> </div> </body> </html>
<html>
  <head>
    <style>
      ...
    </style>
  </head>

  <body>
    <!-- there is no Java script involved at all -->
    <div id="log_in_wrapper">
      <button class='continue_with_google'>
        <a href='step-1-auth-google-get-redirect.php'>
          <img src="some-google-logo"/>
          <span>Continue with Google</span>
        </a>
      </button>
    </div>
  </body>
</html>

This is just another Web app that shows log in buttons. We could skip this step and simply have this buttons in the main WEB app.

For simplicity I only added Log In With google.

This button redirects to step-1-auth-google-get-redirect.php the first part of our authentication service.

 

Creating config file

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?php
// Fill these out with the values you got from Google
$googleClientID = '989056576533-mtef8cl5is5ogjh3np580ireurns7l5k.apps.googleusercontent.com';
$googleClientSecret = 'xxxxxxxxxxxxxx';
// This is the URL we'll send the user to first to get their authorization
$authorizeURL = 'https://accounts.google.com/o/oauth2/v2/auth';
// This is Google's OpenID Connect token endpoint
$tokenURL = 'https://www.googleapis.com/oauth2/v4/token';
// The main application URL. Google will pass JWT token back to the main app
$baseURL = 'https://www.toni-develops.com/external-files/examples/oauth-with-google-with-redirect-step-by-step/step-2-auth-google-redirect.php';
$usserInfoURL = 'https://www.googleapis.com/oauth2/v3/userinfo';
// the initial app url
$initialAppURL = 'https://www.toni-develops.com/2023/01/05/using-oauth2-0-to-log-in-with-google-using-redirect/';
<?php // Fill these out with the values you got from Google $googleClientID = '989056576533-mtef8cl5is5ogjh3np580ireurns7l5k.apps.googleusercontent.com'; $googleClientSecret = 'xxxxxxxxxxxxxx'; // This is the URL we'll send the user to first to get their authorization $authorizeURL = 'https://accounts.google.com/o/oauth2/v2/auth'; // This is Google's OpenID Connect token endpoint $tokenURL = 'https://www.googleapis.com/oauth2/v4/token'; // The main application URL. Google will pass JWT token back to the main app $baseURL = 'https://www.toni-develops.com/external-files/examples/oauth-with-google-with-redirect-step-by-step/step-2-auth-google-redirect.php'; $usserInfoURL = 'https://www.googleapis.com/oauth2/v3/userinfo'; // the initial app url $initialAppURL = 'https://www.toni-develops.com/2023/01/05/using-oauth2-0-to-log-in-with-google-using-redirect/';
<?php

// Fill these out with the values you got from Google
$googleClientID = '989056576533-mtef8cl5is5ogjh3np580ireurns7l5k.apps.googleusercontent.com';
$googleClientSecret = 'xxxxxxxxxxxxxx';

// This is the URL we'll send the user to first to get their authorization
$authorizeURL = 'https://accounts.google.com/o/oauth2/v2/auth';

// This is Google's OpenID Connect token endpoint
$tokenURL = 'https://www.googleapis.com/oauth2/v4/token';

// The main application URL. Google will pass JWT token back to the main app
$baseURL = 'https://www.toni-develops.com/external-files/examples/oauth-with-google-with-redirect-step-by-step/step-2-auth-google-redirect.php';

$usserInfoURL = 'https://www.googleapis.com/oauth2/v3/userinfo';

// the initial app url
$initialAppURL = 'https://www.toni-develops.com/2023/01/05/using-oauth2-0-to-log-in-with-google-using-redirect/';

 

After selecting to log-in with desired authentication provider, call backend service to prepare all necessary parameters and call selected authentication service (Google, Apple, Facebook, GitHub)

step-1-auth-google-get-redirect.php

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?php
// add Google app config params
include 'google-config.php';
// Start a session so we have session id to make sure that the redicect is instantiated by this script
$sessionId = '123';
// ####################################################
// STEP 1: Start the login process by sending the user
// to Google's authorization page,
// and passing app params
// ####################################################
// Generate a random hash and store in the session to make sure that
//$_SESSION['state'] = bin2hex(random_bytes(16));
$params = array(
'response_type' => 'code',
'client_id' => $googleClientID,
'redirect_uri' => $baseURL,
'scope' => 'openid email profile',
'state' => $sessionId
);
// Redirect the user to Google's authorization page, passing the above parameters as a GET request
header('Location: ' . $authorizeURL . '?' . http_build_query($params));
<?php // add Google app config params include 'google-config.php'; // Start a session so we have session id to make sure that the redicect is instantiated by this script $sessionId = '123'; // #################################################### // STEP 1: Start the login process by sending the user // to Google's authorization page, // and passing app params // #################################################### // Generate a random hash and store in the session to make sure that //$_SESSION['state'] = bin2hex(random_bytes(16)); $params = array( 'response_type' => 'code', 'client_id' => $googleClientID, 'redirect_uri' => $baseURL, 'scope' => 'openid email profile', 'state' => $sessionId ); // Redirect the user to Google's authorization page, passing the above parameters as a GET request header('Location: ' . $authorizeURL . '?' . http_build_query($params));
<?php
// add Google app config params
include 'google-config.php';

// Start a session so we have session id to make sure that the redicect is instantiated by this script
$sessionId = '123';

// ####################################################
// STEP 1: Start the login process by sending the user
// to Google's authorization page, 
// and passing app params
// ####################################################


  // Generate a random hash and store in the session to make sure that 
  //$_SESSION['state'] = bin2hex(random_bytes(16));

  $params = array(
    'response_type' => 'code',
    'client_id'     => $googleClientID,
    'redirect_uri'  => $baseURL,
    'scope'         => 'openid email profile',
    'state'         => $sessionId
  );

  // Redirect the user to Google's authorization page, passing the above parameters as a GET request
  header('Location: ' . $authorizeURL . '?' . http_build_query($params));

This simply redirects to the authentication service. In this case Google, passing these parameters:

  • response_type – we requesting code in the response which we are going to exchange it for JWT
  • client_id – is the app id that we registered
  • redirect_url – is our authentication service url, that Google will call passing code parameter. Here we are going to exchange it for JWT In this example this is step-2-auth-google-redirect.php` script below.
  • scope – is the requested scope. In our example we just need user name and email: openid email profile
  • state – this is unique string identifier, that we will check in the callback to make sure that this sign-in workflow is originated by our script

Everything that happens in the above file, could be achieved by simply passing this url in the browser. If you examine the url, it simply passes the same get parameters and query string params.

Next step: Google calls our callback script, passing code which our script exchange for JWT containing user info

step-2-auth-google-redirect.php

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?php
// add Google app config params
include 'google-config.php';
// ####################################################
// Step 2: When Google redirects the user back here,
// there will be a "code" and "state"
// parameter in the query string
// Exchange the auth code for a JWT token,
// and extract requested user data from there
// ####################################################
if(isset($_GET['code'])) {
// Verify the state matches our stored state
if(!$_GET['state'] && $_GET['state'] !== '123') {
die('missing state!');
}
// Exchange the auth code for a token
$ch = curl_init($tokenURL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'grant_type' => 'authorization_code',
'client_id' => $googleClientID,
'client_secret' => $googleClientSecret,
'redirect_uri' => $baseURL,
'code' => $_GET['code']
]));
$response = curl_exec($ch);
// $data will contain
// access_token,
// expires_in,
// scope,
// token_type,
// id_token - which is JWT token, containing user data according to requested scope from the initial script.
$data = json_decode($response, true);
//echo '<pre>';print_r($data);die("</pre>");
// Note: You'd probably want to use a real JWT library
// but this will do in a pinch. This is only safe to do
// because the ID token came from the https connection
// from Google rather than an untrusted browser redirect
// Split the JWT string into three parts
$jwt = explode('.', $data['id_token']);
// Extract the middle part, base64 decode it, then json_decode it
$IDToken = json_decode(base64_decode($jwt[1]), true);
// This step is required only if we want to get extra info
/*
$ch = curl_init($usserInfoURL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer '.$data['access_token']
]);
$userInfo = curl_exec($ch);
*/
/*
echo '<h1>Token ID</h1>';
echo '<pre>';print_r($IDToken);echo '</pre>';
echo '<h1>User info</h1>';
echo '<pre>';print_r($userInfo);die('</pre>');
*/
$params = array(
'email' => $IDToken['email'],
'user_name' => $IDToken['name'],
'given_name' => $IDToken['given_name'],
'family_name' => $IDToken['family_name']
);
// Redirect the user to the initial app passing user data as Query String parameters so the front end could use them.
header('Location: ' . $initialAppURL . '?' . http_build_query($params));
}
else {
echo 'Bad response. Missing `code` GET response';
}
<?php // add Google app config params include 'google-config.php'; // #################################################### // Step 2: When Google redirects the user back here, // there will be a "code" and "state" // parameter in the query string // Exchange the auth code for a JWT token, // and extract requested user data from there // #################################################### if(isset($_GET['code'])) { // Verify the state matches our stored state if(!$_GET['state'] && $_GET['state'] !== '123') { die('missing state!'); } // Exchange the auth code for a token $ch = curl_init($tokenURL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'grant_type' => 'authorization_code', 'client_id' => $googleClientID, 'client_secret' => $googleClientSecret, 'redirect_uri' => $baseURL, 'code' => $_GET['code'] ])); $response = curl_exec($ch); // $data will contain // access_token, // expires_in, // scope, // token_type, // id_token - which is JWT token, containing user data according to requested scope from the initial script. $data = json_decode($response, true); //echo '<pre>';print_r($data);die("</pre>"); // Note: You'd probably want to use a real JWT library // but this will do in a pinch. This is only safe to do // because the ID token came from the https connection // from Google rather than an untrusted browser redirect // Split the JWT string into three parts $jwt = explode('.', $data['id_token']); // Extract the middle part, base64 decode it, then json_decode it $IDToken = json_decode(base64_decode($jwt[1]), true); // This step is required only if we want to get extra info /* $ch = curl_init($usserInfoURL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer '.$data['access_token'] ]); $userInfo = curl_exec($ch); */ /* echo '<h1>Token ID</h1>'; echo '<pre>';print_r($IDToken);echo '</pre>'; echo '<h1>User info</h1>'; echo '<pre>';print_r($userInfo);die('</pre>'); */ $params = array( 'email' => $IDToken['email'], 'user_name' => $IDToken['name'], 'given_name' => $IDToken['given_name'], 'family_name' => $IDToken['family_name'] ); // Redirect the user to the initial app passing user data as Query String parameters so the front end could use them. header('Location: ' . $initialAppURL . '?' . http_build_query($params)); } else { echo 'Bad response. Missing `code` GET response'; }
<?php
// add Google app config params
include 'google-config.php';

// ####################################################
// Step 2: When Google redirects the user back here, 
// there will be a "code" and "state"
// parameter in the query string
// Exchange the auth code for a JWT token,
// and extract requested user data from there
// ####################################################
if(isset($_GET['code'])) {
  
  // Verify the state matches our stored state
  if(!$_GET['state'] && $_GET['state'] !== '123') {    
    die('missing state!');
  }
  
  // Exchange the auth code for a token
  $ch = curl_init($tokenURL);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'grant_type' => 'authorization_code',
    'client_id' => $googleClientID,
    'client_secret' => $googleClientSecret,
    'redirect_uri' => $baseURL,
    'code' => $_GET['code']
  ]));

  $response = curl_exec($ch);

  // $data will contain 
  // access_token, 
  // expires_in, 
  // scope, 
  // token_type, 
  // id_token - which is JWT token, containing user data according to requested scope from the initial script.
  $data = json_decode($response, true);
  //echo '<pre>';print_r($data);die("</pre>");

  // Note: You'd probably want to use a real JWT library
  // but this will do in a pinch. This is only safe to do
  // because the ID token came from the https connection
  // from Google rather than an untrusted browser redirect

  // Split the JWT string into three parts
  $jwt = explode('.', $data['id_token']);

  // Extract the middle part, base64 decode it, then json_decode it
  $IDToken = json_decode(base64_decode($jwt[1]), true);
  
  // This step is required only if we want to get extra info
  /*
  $ch = curl_init($usserInfoURL);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer '.$data['access_token']
  ]);
  $userInfo = curl_exec($ch);
  */
  /*
  echo '<h1>Token ID</h1>';
  echo '<pre>';print_r($IDToken);echo '</pre>';
  echo '<h1>User info</h1>';
  echo '<pre>';print_r($userInfo);die('</pre>');
  */

  $params = array(
    'email'       => $IDToken['email'],
    'user_name'   => $IDToken['name'],
    'given_name'  => $IDToken['given_name'],
    'family_name'  => $IDToken['family_name']
  );

  // Redirect the user to the initial app passing user data as Query String parameters so the front end could use them.
  header('Location: ' . $initialAppURL . '?' . http_build_query($params));
}
else {
  echo 'Bad response. Missing `code` GET response';
}

line 19-30: we make curl request to Google service passing:

  • grant_type – authorization_code
  • client_id – App id
  • client_secret – App secret
  • redirect_uri – should be url registered in Authorized redirect URLs

  • code – this is the code returned by Google as GET parameter

Last step: We are redirecting back to the main app, passing parameters that front end needs (email, user name) as GET or POST params.

Additionally we could save the user into our database, or do some additional work before redirecting to the main app (line 76)

 

Using Oauth2 to sign-in users with Google using Google Java Script Library

Example project here:  Sign-in with Google using Google Java Script library

 

  • Main project
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<head>
<style>
#signIn {
width: 80%;
height: 50%;
display: none;
}
span {
border: 1px solid silver;
padding: 10px;
cursor: pointer;
font-size: 10px;
}
</style>
<script>
function userLoggedIn(userObject) {
document.getElementById('signIn').style.display = 'none';
document.getElementById('head').innerHTML = `Wellcome ${userObject.given_name} ${userObject.family_name} ! <hr/>email: ${userObject.email} `;
}
function showLogInPopup() {
document.getElementById('signIn').style.display = 'block';
}
</script>
</head>
<body>
<h1 id="head">Integrating Google Sign-in for Websites with Google library. <span onclick="showLogInPopup()">Log In</span></h1>
<iframe id="signIn" src="google-sign-in.html"></iframe>
</body>
<head> <style> #signIn { width: 80%; height: 50%; display: none; } span { border: 1px solid silver; padding: 10px; cursor: pointer; font-size: 10px; } </style> <script> function userLoggedIn(userObject) { document.getElementById('signIn').style.display = 'none'; document.getElementById('head').innerHTML = `Wellcome ${userObject.given_name} ${userObject.family_name} ! <hr/>email: ${userObject.email} `; } function showLogInPopup() { document.getElementById('signIn').style.display = 'block'; } </script> </head> <body> <h1 id="head">Integrating Google Sign-in for Websites with Google library. <span onclick="showLogInPopup()">Log In</span></h1> <iframe id="signIn" src="google-sign-in.html"></iframe> </body>
<head>
  <style>
    #signIn {
      width: 80%;
      height: 50%;
      display: none;
    }

    span {
      border: 1px solid silver;
      padding: 10px;
      cursor: pointer;
      font-size: 10px;
    }
  </style>
  <script>
    function userLoggedIn(userObject) {
      document.getElementById('signIn').style.display = 'none';
      document.getElementById('head').innerHTML = `Wellcome ${userObject.given_name} ${userObject.family_name} ! <hr/>email: ${userObject.email} `;
    }

    function showLogInPopup() {
      document.getElementById('signIn').style.display = 'block';
    }
  </script>  
</head>

<body>
  <h1 id="head">Integrating Google Sign-in for Websites with Google library. <span onclick="showLogInPopup()">Log In</span></h1>

  <iframe id="signIn" src="google-sign-in.html"></iframe>
</body>
  • create iFrame with the log in button
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<head>
<script src="https://accounts.google.com/gsi/client" async defer></script>
<script>
function userLoggedIn(credential) {
document.getElementById('log-in-iframe').style.display = 'none';
alert(credential);
}
</script>
</head>
<body>
Log in with Google
<div id="log-in-button">
<div id="g_id_onload"
data-client_id="989056576533-mtef8cl5is5ogjh3np580ireurns7l5k.apps.googleusercontent.com"
data-context="signin"
data-response-type="code"
data-ux_mode="popup"
data-login_uri="https://www.toni-develops.com/external-files/examples/oauth-with-google-with-popup/callback.php"
data-itp_support="true"
data-auto_prompt="false">
</div>
<div class="g_id_signin"
data-type="standard"
data-shape="rectangular"
data-theme="filled_blue"
data-text="signin_with"
data-size="large"
data-logo_alignment="left">
</div>
</div>
</body>
<head> <script src="https://accounts.google.com/gsi/client" async defer></script> <script> function userLoggedIn(credential) { document.getElementById('log-in-iframe').style.display = 'none'; alert(credential); } </script> </head> <body> Log in with Google <div id="log-in-button"> <div id="g_id_onload" data-client_id="989056576533-mtef8cl5is5ogjh3np580ireurns7l5k.apps.googleusercontent.com" data-context="signin" data-response-type="code" data-ux_mode="popup" data-login_uri="https://www.toni-develops.com/external-files/examples/oauth-with-google-with-popup/callback.php" data-itp_support="true" data-auto_prompt="false"> </div> <div class="g_id_signin" data-type="standard" data-shape="rectangular" data-theme="filled_blue" data-text="signin_with" data-size="large" data-logo_alignment="left"> </div> </div> </body>
<head>
    <script src="https://accounts.google.com/gsi/client" async defer></script>
    <script>
        function userLoggedIn(credential) {
            document.getElementById('log-in-iframe').style.display = 'none';
            alert(credential);
        }
    </script>
</head>

<body>
    Log in with Google
    <div id="log-in-button">
        <div id="g_id_onload"
            data-client_id="989056576533-mtef8cl5is5ogjh3np580ireurns7l5k.apps.googleusercontent.com"
            data-context="signin"
            data-response-type="code"
            data-ux_mode="popup"
            data-login_uri="https://www.toni-develops.com/external-files/examples/oauth-with-google-with-popup/callback.php"
            data-itp_support="true"
            data-auto_prompt="false">
        </div>

        <div class="g_id_signin"
            data-type="standard"
            data-shape="rectangular"
            data-theme="filled_blue"
            data-text="signin_with"
            data-size="large"
            data-logo_alignment="left">
        </div>   
    </div>
</body>
  • create callback
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<html>
<head>
</head>
<body>
<pre>
<?php
$token = $_POST['credential'];
$userObject = json_decode(base64_decode(str_replace('_', '/', str_replace('-','+',explode('.', $token)[1]))));
print_r($userObject);
?>
</pre>
<script>
var userObject = {
given_name : "<?php echo $userObject->given_name ?>",
family_name : "<?php echo $userObject->family_name ?>",
email : "<?php echo $userObject->email ?>"
}
function passUserObjectToParentDocument(userObject) {
parent.userLoggedIn(userObject);
}
</script>
<button onclick="passUserObjectToParentDocument(userObject)">continue</button>
</body>
</html>
<html> <head> </head> <body> <pre> <?php $token = $_POST['credential']; $userObject = json_decode(base64_decode(str_replace('_', '/', str_replace('-','+',explode('.', $token)[1])))); print_r($userObject); ?> </pre> <script> var userObject = { given_name : "<?php echo $userObject->given_name ?>", family_name : "<?php echo $userObject->family_name ?>", email : "<?php echo $userObject->email ?>" } function passUserObjectToParentDocument(userObject) { parent.userLoggedIn(userObject); } </script> <button onclick="passUserObjectToParentDocument(userObject)">continue</button> </body> </html>
<html>
<head>
</head>

<body>
  <pre>
  <?php
    $token = $_POST['credential'];
    $userObject = json_decode(base64_decode(str_replace('_', '/', str_replace('-','+',explode('.', $token)[1]))));
    print_r($userObject);
  ?>  
  </pre>
  <script>
  var userObject = {
    given_name : "<?php echo $userObject->given_name ?>",
    family_name : "<?php echo $userObject->family_name ?>",
    email : "<?php echo $userObject->email ?>"
  }

  function passUserObjectToParentDocument(userObject) {
    parent.userLoggedIn(userObject);
  }
  </script>
  <button onclick="passUserObjectToParentDocument(userObject)">continue</button>
</body>
</html>

 

Example project here:  Sign-in with Google using Google Java Script library

Longest Common Substring

Task

Given two strings text1 and text2, return the length of their longest common subsequenceIf there is no common subsequence, return 0.

subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.

  • For example, "ace" is a subsequence of "abcde".

common subsequence of two strings is a subsequence that is common to both strings.

 

Example 1:

Input:

 text1 = "abcde", text2 = "ace" 

Output:

 3  

Explanation:

 The longest common subsequence is "ace" and its length is 3.

Example 2:

Input:

 text1 = "abc", text2 = "abc"

Output:

 3

Explanation:

 The longest common subsequence is "abc" and its length is 3.

Example 3:

Input:

 text1 = "abc", text2 = "def"

Output:

 0

Explanation:

 There is no such common subsequence, so the result is 0.

 

Constraints:

  • 1 <= text1.length, text2.length <= 1000
  • text1 and text2 consist of only lowercase English characters.

This problem was taken from Leetcode Longest Common Subsequence

 

Solution

Copy List with Random Pointer

Task

 

A linked list of length n is given such that each node contains an additional random pointer, which could point to any node in the list, or null.

Construct a deep copy of the list. The deep copy should consist of exactly n brand new nodes, where each new node has its value set to the value of its corresponding original node. Both the next and random pointer of the new nodes should point to new nodes in the copied list such that the pointers in the original list and copied list represent the same list state. None of the pointers in the new list should point to nodes in the original list.

For example, if there are two nodes X and Y in the original list, where X.random --> Y, then for the corresponding two nodes x and y in the copied list, x.random --> y.

Return the head of the copied linked list.

The linked list is represented in the input/output as a list of n nodes. Each node is represented as a pair of [val, random_index] where:

  • val: an integer representing Node.val
  • random_index: the index of the node (range from 0 to n-1) that the random pointer points to, or null if it does not point to any node.

Your code will only be given the head of the original linked list.

 

Example 1:

Input:

 head = [[7,null],[13,0],[11,4],[10,2],[1,0]]

Output:

 [[7,null],[13,0],[11,4],[10,2],[1,0]]

Example 2:

Input:

 head = [[1,1],[2,1]]

Output:

 [[1,1],[2,1]]

Example 3:

Input:

 head = [[3,null],[3,0],[3,null]]

Output:

 [[3,null],[3,0],[3,null]]

 

Constraints:

  • 0 <= n <= 1000
  • -104 <= Node.val <= 104
  • Node.random is null or is pointing to some node in the linked list.

This problem was taken from https://leetcode.com/problems/copy-list-with-random-pointer/

Solution

Range Sum of BST

Task

Given the root node of a binary search tree and two integers low and high, return the sum of values of all nodes with a value in the inclusive range [low, high].

 

Example 1:

Input:

 root = [10,5,15,3,7,null,18], low = 7, high = 15

Output:

 32

Explanation:

 Nodes 7, 10, and 15 are in the range [7, 15]. 7 + 10 + 15 = 32.

Example 2:

Input:

 root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10

Output:

 23

Explanation:

 Nodes 6, 7, and 10 are in the range [6, 10]. 6 + 7 + 10 = 23.

 

Constraints:

  • The number of nodes in the tree is in the range [1, 2 * 104].
  • 1 <= Node.val <= 105
  • 1 <= low <= high <= 105
  • All Node.val are unique.

This problem was taken from https://leetcode.com/problems/range-sum-of-bst/

 

Solution