Apollo is a configuration management system and will provide authority management (Authorization), theoretically it is not responsible for the implementation of user login authentication function (Authentication).

So Apollo defines some SPI’s for decoupling and the key to Apollo access login is to implement these SPI’s.

Implementation 1: Simple authentication using Spring Security provided by Apollo

Apollo provides a simple authentication version of Http Basic using Spring Security since 0.9.0 for this situation.

Use the following steps.

1. Install 0.9.0 or above

If the previous version is 0.8.0, you need to import apolloportaldb-v080-v090.sql

Checking ApolloPortalDB, the Users table should already exist and have an initial record. The initial user name is apollo and the password is admin.

Id Username Password Email Enabled
1 apollo $2a$10$7r20uS.BQ9uBpf3Baj3uQOZvMVvB1RN3PYoKE94gtz2.WAOuiiwXS apollo@acme.com 1

2. Reboot the Portal

Make sure -Dapollo_profile=github,auth if it is started by IDE

3. Add users

Super Administrator can add users by opening Administrator Tools - User Management after logging into the system.

4. Change user password

After logging in, open Administrator Tools - User Management and enter the user name and password to change the user’s password, we recommend changing the password of super administrator apollo at the same time.

Implementation 2: Access to LDAP

Starting from version 1.2.0, Apollo supports ldap protocol login, which can be configured as follows.

If you use helm chart deployment method, it is recommended to implement it by configuration method without modifying the image, you can refer to Enable LDAP support

1. OpenLDAP access method

1.1 Configure application-ldap.yml

After unpacking apollo-portal-x.x.x-github.zip, create application-ldap.yml in the config directory with the following reference (sample) , the relevant content needs to be adjusted according to the specific situation:

  1. spring:
  2. ldap:
  3. base: "dc=example,dc=org"
  4. username: "cn=admin,dc=example,dc=org" # Configure administrator account for searching and matching users
  5. password: "password"
  6. searchFilter: "(uid={0})" # user filter, use this filter to search for users when logging in
  7. urls:
  8. - "ldap://localhost:389"
  9. ldap:
  10. mapping: # Configure the ldap attribute
  11. objectClass: "inetOrgPerson" # ldap user objectClass configuration
  12. loginId: "uid" # ldap user unique id, used as the login id
  13. userDisplayName: "cn" # ldap user name, used as display name
  14. email: "mail" # ldap mailbox attribute
1.1.1 Filtering users based on memberOf

With OpenLDAP memberOf feature enabled, the filter can be configured to narrow down the users to search for.

  1. spring:
  2. ldap:
  3. base: "dc=example,dc=org"
  4. username: "cn=admin,dc=example,dc=org" # Configure admin account for searching and matching users
  5. password: "password"
  6. searchFilter: "(uid={0})" # user filter, use this filter to search for users when logging in
  7. urls:
  8. - "ldap://localhost:389"
  9. ldap:
  10. mapping: # Configure the ldap attribute
  11. objectClass: "inetOrgPerson" # ldap user objectClass configuration
  12. loginId: "uid" # ldap user unique id, used as the login id
  13. userDisplayName: "cn" # ldap user name, used as display name
  14. email: "mail" # ldap mailbox attribute
  15. filter: # Configuration filter, currently only memberOf is supported
  16. memberOf: "cn=ServiceDEV,ou=DEV,dc=example,dc=org|cn=WebDEV,ou=DEV,dc=example,dc=org" # Only allow users with memberOf attribute of ServiceDEV and WebDEV to access
1.1.2 Filtering users based on Group

Starting with version 1.3.0, we support filtering users based on Group, which allows you to control that only users of a specific Group can log in and use apollo.

  1. spring:
  2. ldap:
  3. base: "dc=example,dc=org"
  4. username: "cn=admin,dc=example,dc=org" # Configure admin account for searching and matching users
  5. password: "password"
  6. searchFilter: "(uid={0})" # user filter, use this filter to search for users when logging in
  7. urls:
  8. - "ldap://localhost:389"
  9. ldap:
  10. mapping: # Configure the ldap attribute
  11. objectClass: "inetOrgPerson" # ldap user objectClass configuration
  12. loginId: "uid" # ldap user unique id, used as login id
  13. rdnKey: "uid" # ldap rdn key
  14. userDisplayName: "cn" # ldap user name, used as display name
  15. email: "mail" # ldap mailbox attribute
  16. group: # enable group search, only users of a specific group can login to apollo after enabling
  17. objectClass: "posixGroup" # Configure groupClassName
  18. groupBase: "ou=group" # group search base
  19. groupSearch: "(&(cn=dev))" # group filter
  20. groupMembership: "memberUid" # group memberShip eg. member or memberUid

1.2 Configure startup.sh

Modify scripts/startup.sh to specify spring.profiles.active as github,ldap.

  1. SERVICE_NAME=apollo-portal
  2. ## Adjust log dir if necessary
  3. LOG_DIR=/opt/logs/100003173
  4. ## Adjust server port if necessary
  5. SERVER_PORT=8070
  6. export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=github,ldap"
  7. `

2. Active Directory access method

2.1 Configure application-ldap.yml

After unpacking apollo-portal-x.x.x-github.zip, create application-ldap.yml in the config directory with the following reference (sample) , the relevant content needs to be adapted to the specific case:

  1. spring:
  2. ldap:
  3. base: "dc=example,dc=com"
  4. username: "admin" # Configure administrator account for searching and matching users
  5. password: "password"
  6. searchFilter: "(sAMAccountName={0})" # user filter, use this filter to search for users when logging in
  7. urls:
  8. - "ldap://1.1.1.1:389"
  9. ldap:
  10. mapping: # Configure the ldap attribute
  11. objectClass: "user" # ldap user objectClass configuration
  12. loginId: "sAMAccountName" # the unique id of the ldap user, used as the login id
  13. userDisplayName: "cn" # ldap user name, used as display name
  14. email: "userPrincipalName" # ldap mailbox attribute
  15. filter: # optional, configure filter, currently only support memberOf
  16. memberOf: "CN=ServiceDEV,OU=test,DC=example,DC=com|CN=WebDEV,OU=test,DC=example,DC=com" # Only allow users with memberOf attribute of ServiceDEV and WebDEV to access

2.2 Configure startup.sh

Modify scripts/startup.sh to specify spring.profiles.active as github,ldap.

  1. SERVICE_NAME=apollo-portal
  2. ## Adjust log dir if necessary
  3. LOG_DIR=/opt/logs/100003173
  4. ## Adjust server port if necessary
  5. SERVER_PORT=8070
  6. export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=github,ldap"
  7. `

3. ApacheDS access method

3.1 Configure application-ldap.yml

After unpacking apollo-portal-x.x.x-github.zip, create application-ldap.yml in the config directory with the following reference (sample) , the relevant content needs to be adjusted according to the specific situation:

  1. spring:
  2. ldap:
  3. base: "dc=example,dc=com"
  4. username: "uid=admin,ou=system" # Configure administrator account for searching and matching users
  5. password: "password"
  6. searchFilter: "(uid={0})" # user filter, use this filter to search for users when logging in
  7. urls:
  8. - "ldap://localhost:10389"
  9. ldap:
  10. mapping: # Configure the ldap attribute
  11. objectClass: "inetOrgPerson" # ldap user objectClass configuration
  12. loginId: "uid" # ldap user unique id, used as the login id
  13. userDisplayName: "displayName" # ldap user name, used as display name
  14. email: "mail" # ldap mailbox attribute
3.1.1 Filtering users based on Groups

Starting with version 1.3.0, we support filtering users based on Group, which allows you to control that only users of a specific Group can log in and use apollo.

  1. spring:
  2. ldap:
  3. base: "dc=example,dc=com"
  4. username: "uid=admin,ou=system" # Configure admin account for searching and matching users
  5. password: "password"
  6. searchFilter: "(uid={0})" # user filter, use this filter to search for users when logging in
  7. urls:
  8. - "ldap://localhost:10389"
  9. ldap:
  10. mapping: # Configure the ldap attribute
  11. objectClass: "inetOrgPerson" # ldap user objectClass configuration
  12. loginId: "uid" # ldap user unique id, used as the login id
  13. rdnKey: "cn" # ldap rdn key
  14. userDisplayName: "displayName" # ldap user name, used as display name
  15. email: "mail" # ldap mailbox attribute
  16. group: # Configure ldap group, only users of specific group can login apollo after enabled
  17. objectClass: "groupOfNames" # Configure groupClassName
  18. groupBase: "ou=group" # group search base
  19. groupSearch: "(&(cn=dev))" # group filter
  20. groupMembership: "member" # group memberShip eg. member or memberUid

3.2 Configuring startup.sh

Modify scripts/startup.sh to specify spring.profiles.active as github,ldap.

  1. SERVICE_NAME=apollo-portal
  2. ## Adjust log dir if necessary
  3. LOG_DIR=/opt/logs/100003173
  4. ## Adjust server port if necessary
  5. SERVER_PORT=8070
  6. export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=github,ldap"
  7. `

Implementation 3: Access to OIDC

Since version 1.8.0 OpenID Connect login is supported, this implementation requires that the OpenID Connect login service has been deployed
Before configuration, you need to prepare:

1. Configure application-oidc.yml

After unpacking apollo-portal-x.x.x-github.zip, create application-oidc.yml in the config directory with the following contents (sample) , the relevant content needs to be adapted to the specific case:

1.1 Minimum configuration

  1. server:
  2. # Parse reverse proxy request headers
  3. forward-headers-strategy: framework
  4. spring:
  5. security:
  6. oauth2:
  7. client:
  8. provider:
  9. # provider-name is the name of the oidc provider, any character is fine, it is required for registration configuration
  10. <fill-in-the-provider-name-here>:
  11. # must be https, issuer-uri of oidc
  12. # For example, if your issuer-uri is https://host:port/auth/realms/apollo/.well-known/openid-configuration, then here you only need to configure https://host:port/auth/realms/ apollo, spring boot will process it with the /.well known/openid-configuration suffix
  13. issuer-uri: https://host:port/auth/realms/apollo
  14. registration:
  15. # registration-name is the name of the oidc client, any character is fine, oidc login must be configured with a registration of type authorization_code
  16. <fill-in-the-registration-name-here>:
  17. # oidc login must be configured with a registration of authorization_code type
  18. authorization-grant-type: authorization_code
  19. client-authentication-method: basic
  20. # client-id is the client ID configured at the oidc provider, used to log in to the provider
  21. client-id: apollo-portal
  22. # The name of the provider, which should be the same as the provider name configured above
  23. provider: <fill-in-the-provider-name-here>
  24. # openid is the required scope for oidc login, you can add other custom scopes here
  25. scope:
  26. - openid
  27. # client-secret is the client password configured at the oidc provider, used to log in to the provider
  28. # From the security point of view, it is recommended to use environment variables, which should be named as follows: dot(.), crossbar(-) The naming rule for environment variables is: replace the dot (.) and the crossbar (-) in the key of the configuration item with an underscore (_), then change all letters to uppercase, spring boot will automatically process environment variables that match this rule
  29. # For example, spring.security.oauth2.client.registration.registration-name.client-secret -> SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_NAME_ VDISK_CLIENT_SECRET (REGISTRATION_NAME can be replaced with the name of a custom oidc client)
  30. client-secret: d43c91c0-xxxx-xxxx-xxxx-xxxxxxxxxxxx

1.2 Extended Configuration

  • If the OpenID Connect login service supports client_credentials mode, you can also configure a registration of type client_credentials, which can be used by apollo-portal as a client to request other resources protected by oidc
  • If the OpenID Connect login service supports jwt, you can also configure ${spring.security.oauth2.resourceserver.jwt.issuer-uri} to support accessing apollo-portal via jwt
  1. server:
  2. # Parse reverse proxy request headers
  3. forward-headers-strategy: framework
  4. spring:
  5. security:
  6. oauth2:
  7. client:
  8. provider:
  9. # provider-name is the name of the oidc provider, any character is fine, it is required for registration configuration
  10. <fill-in-the-provider-name-here>:
  11. # must be the issuer-uri of https, oidc, and jwt if it is the same as the issuer-uri of jwt, or you can set it separately
  12. issuer-uri: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}
  13. registration:
  14. # registration-name is the name of the oidc client, any character is fine, oidc login must be configured with a registration of type authorization_code
  15. <fill-in-the-registration-name-here>:
  16. # oidc login must be configured with a registration of authorization_code type
  17. authorization-grant-type: authorization_code
  18. client-authentication-method: basic
  19. # client-id is the client ID configured at the oidc provider, used to log in to the provider
  20. client-id: apollo-portal
  21. # The name of the provider, which should be the same as the provider name configured above
  22. provider: <fill-in-the-provider-name-here>
  23. # openid is the required scope for oidc login, you can add other custom scopes here
  24. scope:
  25. - openid
  26. # client-secret is the client password configured at the oidc provider, used to log in to the provider
  27. # From the security point of view, it is recommended to use environment variables, which should be named as follows: dot(.), crossbar(-) The naming rule for environment variables is: replace the dot (.) and the crossbar (-) in the key of the configuration item with an underscore (_), then change all letters to uppercase, spring boot will automatically process environment variables that match this rule
  28. # For example, spring.security.oauth2.client.registration.registration-name.client-secret -> SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_NAME_ VDISK_CLIENT_SECRET (REGISTRATION_NAME can be replaced with the name of a custom oidc client)
  29. client-secret: d43c91c0-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  30. # registration-name-client is the name of the oidc client, any character is allowed, registration of client_credentials type is optional, can not be configured
  31. registration-name-client:
  32. # registration of client_credentials type is optional, used by apollo-portal as a client to request other oidc-protected resources, may not be configured
  33. authorization-grant-type: client_credentials
  34. client-authentication-method: basic
  35. # client-id is the client ID configured at the oidc provider, used to log in to the provider
  36. client-id: apollo-portal
  37. # The name of the provider, which must be the same as the provider name configured above
  38. provider: <fill-in-the-provider-name-here>
  39. # openid is the required scope for oidc login, you can add other custom scopes here
  40. scope:
  41. - openid
  42. # client-secret is the client password configured at the oidc provider, used to log in to the provider, multiple registrations can be referenced if the password is the same
  43. client-secret: ${spring.security.oauth2.client.registration.registration-name.client-secret}
  44. resourceserver:
  45. jwt:
  46. # must be issuer-uri for https, jwt
  47. # For example, if your issuer-uri is https://host:port/auth/realms/apollo/.well-known/openid-configuration, then here you only need to configure https://host:port/auth/realms/ apollo, spring boot will automatically add the /.well known/openid-configuration suffix when processing
  48. issuer-uri: https://host:port/auth/realms/apollo

2. Configure startup.sh

Modify scripts/startup.sh to specify spring.profiles.active as github,oidc.

  1. SERVICE_NAME=apollo-portal
  2. ## Adjust log dir if necessary
  3. LOG_DIR=/opt/logs/100003173
  4. ## Adjust server port if necessary
  5. SERVER_PORT=8070
  6. export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active=github,oidc"
  7. `

3. Configure apollo-portal to enable https

3.1 Adding a reverse proxy header

Using nginx as an example, add or include (recommended) the following configuration directly to the http configuration section of nginx

  1. server {
  2. listen 80 default_server;
  3. location / {
  4. # redirect all requests on port 80 to https
  5. return 301 https://$http_host$request_uri;
  6. }
  7. }
  8. server {
  9. # For lower versions of nginx that do not support http2, configure listen 443 ssl;
  10. listen 443 ssl http2;
  11. server_name xxx;
  12. # ssl certificate, nginx needs to use a full certificate chain certificate
  13. ssl_certificate /etc/nginx/ssl/xxx.crt;
  14. ssl_certificate_key /etc/nginx/ssl/xxx.key;
  15. # ... The rest of the ssl configuration
  16. location / {
  17. proxy_pass http://apollo-portal-dev:8070;
  18. proxy_set_header x-real-ip $remote_addr;
  19. proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
  20. # !!! Here must be $http_host, if configured as $host, it will cause the port error when jumping
  21. proxy_set_header host $http_host;
  22. proxy_set_header x-forwarded-proto $scheme;
  23. proxy_http_version 1.1;
  24. proxy_set_header}
  25. }

3.2 Checking the application-oidc.yml configuration

The configuration item server.forward-headers-strategy=framework must exist in application-oidc.yml.

  1. server:
  2. # Parse reverse proxy request headers
  3. forward-headers-strategy: framework

3.3 Adding a whitelist of redirects for the OpenID Connect login service

For security reasons, the OpenID Connect login service generally has a whitelist of redirected addresses, so you need to add the apollo-portal https address to the whitelist in order to redirect properly.

Implementation 4: access to the company’s unified login authentication system

This approach assumes that the company already has a unified login authentication system, such as SSO and LDAP. The following SPI must be implemented to access the system, including UserService and UserInfoHolder.

The interfaces are described as follows.

  • UserService (Required): User service, used to provide user search-related functions to the Portal
  • UserInfoHolder (Required): Get the current login user information, SSO is generally the current login user information on ThreadLocal
  • LogoutHandler (Optional): used to implement the logout function
  • SsoHeartbeatHandler (Optional): If the Portal page is not refreshed for a long time, the login information will expire. Refresh the login information through this interface

You can refer to apollo-portal module’s package of com.ctrip.framework.apollo.portal.spi , under this package for four implementations.

  1. defaultimpl: default implementation, with only one global apollo account
  2. ctrip: ctrip implementation, access to the SSO and the implementation of the user search, query interface
  3. springsecurity: spring security implementation, you can add new users, modify the user password, etc.
  4. ldap: ldap implementation contributed by @pandalin and codepiano

After implementing the relevant interfaces, the AuthConfiguration can be accessed via com.ctrip.framework.apollo.portal.configuration to replace the default implementation at runtime.

The idea of accessing SSO is as follows.

  1. SSO will provide a jar package, you need to configure a filter
  2. filter will intercept all requests and check if you are already logged in
  3. if there is no login, then it will jump to the SSO login page
  4. After successful login in the SSO login page, it will jump back to the apollo page with the authentication information. 5.
  5. enter the SSO filter again, verify the authentication information, save the user’s information, and write the user’s credentials to a cookie or distributed session to avoid having to log in again next time
  6. enter Apollo’s code, Apollo’s code will call UserInfoHolder.getUser to get the current logged-in user

Note that the above steps 1-5 are all SSO code, not Apollo code, Apollo code only requires you to implement step 6.

Note: The runtime use of different implementations is achieved by Profiles. For example, if your own sso implementation is in the custom profile, you can specify -Dapollo_profile=github,custom in the packaging script. profile. Also note that in AuthConfiguration to modify the default implementation of the condition , from @ConditionalOnMissingProfile({"ctrip", "auth", "ldap"}) to @ConditionalOnMissingProfile({"ctrip", "auth", "ldap", "custom"}).