diff --git a/static/images/landing-page/logos/azuread-icon.png b/static/images/landing-page/logos/azuread-icon.png
new file mode 100644
index 0000000000..70ad2210e7
Binary files /dev/null and b/static/images/landing-page/logos/azuread-icon.png differ
diff --git a/static/images/landing-page/logos/github-icon.png b/static/images/landing-page/logos/github-icon.png
new file mode 100644
index 0000000000..182a1a3f73
Binary files /dev/null and b/static/images/landing-page/logos/github-icon.png differ
diff --git a/static/styles/portico/portico-signin.scss b/static/styles/portico/portico-signin.scss
index 842e5cdc45..9b9e1e07d7 100644
--- a/static/styles/portico/portico-signin.scss
+++ b/static/styles/portico/portico-signin.scss
@@ -632,36 +632,6 @@ button.login-social-button:active {
     box-shadow: 0px 1px 1px hsla(0, 0%, 0%, 0.3);
 }
 
-.saml-wrapper button.login-social-button {
-    background-image: url('/static/images/landing-page/logos/saml-icon.png');
-    width: 100%;
-}
-
-.google-wrapper button.login-social-button {
-    background-image: url('/static/images/landing-page/logos/googl_e-icon.png');
-    width: 100%;
-}
-
-.github-wrapper::before {
-    content: "\f09b";
-    position: absolute;
-
-    font-family: "FontAwesome";
-    font-size: 2rem;
-    color: hsl(0, 0%, 20%);
-    transform: translateX(15px) translateY(13px);
-}
-
-.azuread-oauth2-wrapper::before {
-    content: "\f17a";
-    position: absolute;
-
-    font-family: "FontAwesome";
-    font-size: 2rem;
-    color: hsl(0, 0%, 20%);
-    transform: translateX(15px) translateY(13px);
-}
-
 .login-page-container .right-side .actions,
 .forgot-password-container .actions {
     margin: 20px 0px 0px;
diff --git a/templates/zerver/accounts_home.html b/templates/zerver/accounts_home.html
index 5700ea4290..aec0771584 100644
--- a/templates/zerver/accounts_home.html
+++ b/templates/zerver/accounts_home.html
@@ -75,9 +75,9 @@ page can be easily identified in it's respective JavaScript file -->
 
                         {% for backend in social_backends %}
                         
-                            
diff --git a/templates/zerver/login.html b/templates/zerver/login.html
index 9952e0ceff..e5618feb15 100644
--- a/templates/zerver/login.html
+++ b/templates/zerver/login.html
@@ -132,9 +132,9 @@ page can be easily identified in it's respective JavaScript file. -->
 
                         {% for backend in social_backends %}
                         
-                            
diff --git a/tools/linter_lib/custom_check.py b/tools/linter_lib/custom_check.py
index c2848fc963..f0034f4d86 100644
--- a/tools/linter_lib/custom_check.py
+++ b/tools/linter_lib/custom_check.py
@@ -676,6 +676,10 @@ html_rules = whitespace_rules + prose_style_rules + [
          'templates/zerver/email.html',
          'templates/zerver/email_log.html',
 
+         # Social backend logos are dynamically loaded
+         'templates/zerver/accounts_home.html',
+         'templates/zerver/login.html',
+
          # Probably just needs to be changed to display: none so the exclude works
          'templates/zerver/app/navbar.html',
 
diff --git a/zerver/context_processors.py b/zerver/context_processors.py
index 7348528146..05dd333234 100644
--- a/zerver/context_processors.py
+++ b/zerver/context_processors.py
@@ -3,16 +3,15 @@ from urllib.parse import urljoin
 from typing import Any, Dict, Optional
 from django.http import HttpRequest
 from django.conf import settings
-from django.urls import reverse
 
 from zerver.models import UserProfile, get_realm, Realm
 from zproject.backends import (
     any_social_backend_enabled,
+    get_social_backend_dicts,
     password_auth_enabled,
     require_email_format_usernames,
     auth_enabled_helper,
     AUTH_BACKEND_NAME_MAP,
-    SOCIAL_AUTH_BACKENDS,
 )
 from zerver.decorator import get_client_name
 from zerver.lib.send_email import FromAddress
@@ -168,7 +167,6 @@ def login_context(request: HttpRequest) -> Dict[str, Any]:
 
     # Add the keys for our standard authentication backends.
     no_auth_enabled = True
-    social_backends = []
     for auth_backend_name in AUTH_BACKEND_NAME_MAP:
         name_lower = auth_backend_name.lower()
         key = "%s_auth_enabled" % (name_lower,)
@@ -177,19 +175,7 @@ def login_context(request: HttpRequest) -> Dict[str, Any]:
         if is_enabled:
             no_auth_enabled = False
 
-        # Now add the enabled social backends to the social_backends
-        # list used to generate buttons for login/register pages.
-        backend = AUTH_BACKEND_NAME_MAP[auth_backend_name]
-        if not is_enabled or backend not in SOCIAL_AUTH_BACKENDS:
-            continue
-        social_backends.append({
-            'name': backend.name,
-            'display_name': backend.auth_backend_name,
-            'login_url': reverse('login-social', args=(backend.name,)),
-            'signup_url': reverse('signup-social', args=(backend.name,)),
-            'sort_order': backend.sort_order,
-        })
-    context['social_backends'] = sorted(social_backends, key=lambda x: x['sort_order'], reverse=True)
+    context['social_backends'] = get_social_backend_dicts(realm)
     context['no_auth_enabled'] = no_auth_enabled
 
     return context
diff --git a/zproject/backends.py b/zproject/backends.py
index 6a091bcba9..23c2c48c62 100644
--- a/zproject/backends.py
+++ b/zproject/backends.py
@@ -17,6 +17,7 @@ import logging
 import magic
 import ujson
 from typing import Any, Dict, List, Optional, Set, Tuple, Union
+from typing_extensions import TypedDict
 
 from django_auth_ldap.backend import LDAPBackend, LDAPReverseEmailSearch, \
     _LDAPUser, ldap_error
@@ -992,6 +993,9 @@ def social_auth_finish(backend: Any,
 
 class SocialAuthMixin(ZulipAuthMixin):
     auth_backend_name = "undeclared"
+    name = "undeclared"
+    display_logo = None  # type: Optional[str]
+
     # Used to determine how to order buttons on login form, backend with
     # higher sort order are displayed first.
     sort_order = 0
@@ -1020,8 +1024,10 @@ class SocialAuthMixin(ZulipAuthMixin):
             return None
 
 class GitHubAuthBackend(SocialAuthMixin, GithubOAuth2):
+    name = "github"
     auth_backend_name = "GitHub"
     sort_order = 100
+    display_logo = "/static/images/landing-page/logos/github-icon.png"
 
     def get_verified_emails(self, *args: Any, **kwargs: Any) -> List[str]:
         access_token = kwargs["response"]["access_token"]
@@ -1085,12 +1091,15 @@ class GitHubAuthBackend(SocialAuthMixin, GithubOAuth2):
 
 class AzureADAuthBackend(SocialAuthMixin, AzureADOAuth2):
     sort_order = 50
+    name = "azuread-oauth2"
     auth_backend_name = "AzureAD"
+    display_logo = "/static/images/landing-page/logos/azuread-icon.png"
 
 class GoogleAuthBackend(SocialAuthMixin, GoogleOAuth2):
     sort_order = 150
     auth_backend_name = "Google"
     name = "google"
+    display_logo = "/static/images/landing-page/logos/googl_e-icon.png"
 
     def get_verified_emails(self, *args: Any, **kwargs: Any) -> List[str]:
         verified_emails = []    # type: List[str]
@@ -1105,10 +1114,12 @@ class SAMLAuthBackend(SocialAuthMixin, SAMLAuth):
     standard_relay_params = ["subdomain", "multiuse_object_key", "mobile_flow_otp",
                              "next", "is_signup"]
     REDIS_EXPIRATION_SECONDS = 60 * 15
+    name = "saml"
     # Organization which go through the trouble of setting up SAML are most likely
     # to have it as their main authentication method, so it seems appropriate to have
     # SAML buttons at the top.
     sort_order = 9999
+    display_logo = "/static/images/landing-page/logos/saml-icon.png"
 
     def auth_url(self) -> str:
         """Get the URL to which we must redirect in order to
@@ -1222,6 +1233,34 @@ class SAMLAuthBackend(SocialAuthMixin, SAMLAuth):
 
         return result
 
+SocialBackendDictT = TypedDict('SocialBackendDictT', {
+    'name': str,
+    'display_name': str,
+    'display_logo': str,
+    'login_url': str,
+    'signup_url': str,
+    'sort_order': int,
+})
+
+def create_standard_social_backend_dict(social_backend: SocialAuthMixin) -> SocialBackendDictT:
+    assert social_backend.display_logo is not None
+    return dict(
+        name=social_backend.name,
+        display_name=social_backend.auth_backend_name,
+        display_logo=social_backend.display_logo,
+        login_url=reverse('login-social', args=(social_backend.name,)),
+        signup_url=reverse('signup-social', args=(social_backend.name,)),
+        sort_order=social_backend.sort_order
+    )
+
+def get_social_backend_dicts(realm: Optional[Realm]=None) -> List[SocialBackendDictT]:
+    result = []
+    for backend in SOCIAL_AUTH_BACKENDS:
+        if auth_enabled_helper([backend.auth_backend_name], realm):
+            result.append(create_standard_social_backend_dict(backend))
+
+    return sorted(result, key=lambda x: x['sort_order'], reverse=True)
+
 AUTH_BACKEND_NAME_MAP = {
     'Dev': DevAuthBackend,
     'Email': EmailAuthBackend,