ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SpringSecurity OAuth2.0 - 1
    BackEnd/SpringSecurity 2023. 7. 8. 17:51

    1. 스프링 시큐리티에서 사용하는 OAuth2.0 모듈

    SpringSecurity 5

    1. Client Support

    2. ResourceServer

     

    Authorization Server  별도 프로젝트로 존재

    1.1 OAuth2.0 Client 개요

    OAuth2.0 인가 프레임워크의 역할 중 인가서버 및 리소스 서버와의 통신의 담당하는 클라이언트의 기능을 필터기반으로 구현한 모듈

    간단한 설정만으로 OAuth2.0 인증 및 리소스 접근 권한, 인가서버 엔드 포인트 통신등의 구현이 가능하며 커스터마이징의 확장이 용이하다.

     

    1.2 클라이언트 역할하는 모듈 2가지

    1. OAuth2.0 Login

    어플리케이션의 사용자를 외부 OAuth2.0 Provider나 OpenID Connect 1.0Provider 계정으로 로그인할 수 있는 기능을 제공한다.

    인증서버 권한 유형 :Authorization Code 방식을 사용한다.

     

    2. OAuth2.0 Client 

    인증서버 권한 유형 : Client Credentials, Resource Owner Password Credentials, Refresh Token 방식을 지원

    리소스 서버의 보호자원 접근에 대한 연동 모듈을 구현 할 수 있다.

     

    1.3 클라이언트 권한부여 기본 설정

    1. 클라이언트가 인가 서버로 권한 부여, 토큰 요청 시 클라이언트 정보 및 엔드포인트 정보를 참조해서 전달

    2. application.yaml 환경 설정 파일에 클라이언트 설정과 인가서버 엔드포인트 설정

    3. 초기화 진행시 application.yml에 클라이언트 및 엔드포인트 정보가 OAuth2ClientProperties의 각 속성에 바인딩됨

    4. OAuth2ClientProperties 에 바인딩 되어있는 속성의 값은 인가 서버로 권한 부여 요청 하기 위한 ClientRegistration 클래스 필드에 저장

    5. OAuth2Client는 ClientRegistration을 참조해서 권한부여 요청을 위한 매개변수로 구성하고 인가서버와 통신한다. 

    OAuth2ClientProperties

    2. 스프링 시큐리티 applicaion.yaml 설정 또는 빈 설정

    localhost:8080 -> console -> client -> oauth2-client-app 클릭하여 정보 참조

    주의 : redirect_uri가 바뀌었기떄문에 위 화면에서 valid redirectURIs를 http://localhost:8081/login/oauth2/code/keycloak으로 변경

    application.yaml 파일에 다음과 같이 작성

     

    2.1 yaml 설정 또는 bean설정

    server:
      port: 8081
    
    spring:
      security:
        oauth2:
          client: # 클라이언트 설정
            registration:
              keycloak:
                client-id: oauth2-client-app  # 서비스 공급자에 등록된 클라이언트 아이디
                client-name: oauth2-client-app  # 클라이언트 이름
                client-secret: BEcxjQZth2VU0A9llS8hwE3qJXvNMLXR  # 서비스 공급자에 등록된 클라이언트 비밀번호
                redirect-uri: http://localhost:8081/login/oauth2/code/keycloak # 인가코드 부여후 클라이언트로 리다이렉트되는 위치 - 기본스프링설정이/login/oauth2/code까지 규약되어있다.
                authorization-grant-type: authorization_code # 권한 부여 타입
                client-authentication-method: client_secret_basic # 클라이언트 자격증명 전송 방식 - client_secret_basic는 base64 인코딩 후 헤더로 넘기는 방식 그 외에 post, none
                scope: # 리로스 제한 범위
                  - openid
                  - profile
                  - email
            # http://localhost:8080/realms/oauth2/.well-known/openid-configuration 참조하여 작성
            provider: # 공급자 설정
              keycloak:
                authorization-uri: http://localhost:8080/realms/oauth2/protocol/openid-connect/auth # 권한 부여 엔드포인트
                token-uri: http://localhost:8080/realms/oauth2/protocol/openid-connect/token # 서비스 공급자 위치
                issuer-uri: http://localhost:8080/realms/oauth2 # OAuth2.0 JwkSetUri 엔드포인트
                user-info-uri: http://localhost:8080/realms/oauth2/protocol/openid-connect/userinfo # OAuth2.0 토큰 엔드 포인트
                jwk-set-uri: http://localhost:8080/realms/oauth2/protocol/openid-connect/certs # OAuth2.0 UserInfo 엔드 포인트
                user-name-attribute: preferred_username # 사용자명을 추출하는 클레임명

     

    2.2 yaml 설정 또는 bean설정

    package io.security.oauth2.springsecurityoauth2;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.oauth2.client.registration.ClientRegistration;
    import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
    import org.springframework.security.oauth2.client.registration.ClientRegistrations;
    import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
    
    
    @Configuration
    public class OAuth2ClientConfig {
    
        @Bean
        public ClientRegistrationRepository clientRegistrationRepository() {
            return new InMemoryClientRegistrationRepository(keycloackClientRegistration());
        }
    
        private ClientRegistration keycloackClientRegistration() {
    
            return ClientRegistrations.fromIssuerLocation("http://localhost:8080/realms/oauth2")
                    .clientId("oauth2-client-app")
                    .clientSecret("BEcxjQZth2VU0A9llS8hwE3qJXvNMLXR")
                    .redirectUri("http://localhost:8081/login/oauth2/code/keycloak")
                    .build();
        }
    }

    3. 스프링 시큐리티 ClientRegistrations 초기화 과정

    사실 issuerUri, clientId, clientSecret 외에는 필수 값이 아니기때문에 설정하지않아도 OIDC, AUTH Uri로 요청을 보내 필요한 정보를 가져온다.

    하지만 수동으로 yaml이나 bean에 강제로 넣어 사용할 수도 있다.

    yaml파일에 엔드포인트를 지정하는경우 issuer uri를 통해서 정해진 엔드포인트인 OIDC나 AUTH uri로 요청을보내서 값을 가져와도 yaml파일 정보를 우선으로 한다.

    fromIssuerLocaion을 통해서 기본적인 엔드포인트 정보를 가져오고 메타 정보를 생성한다.
    OAuth2ClientRegistrationRepositoryConfiguration에서 yaml로 선언한 provider와 registraion 정보 맵핑
    OAuth2ClientPropertiesRegistrationAdapter클래스에서 getBuilderFromIssuerIfPossible로 Provider정보를 가져온다.
    Get요청(/.well-known/openid-configuration)을 통해서 서버 엔드포인트 정보를 가져온다.
    가져온정보를 다시한번 빌드하면서 properties에 설정한 값이 있다면 그 값을 우선으로 set하여 변경하게된다.
    글로벌 서비스 기업의 정보는 CommonOAuth2Provider로 기본 제공된다. ( 따라서 위 서비스들은 provider를  yaml에 설정 할 필요가 없다. )

    빌드과정에서 issuer_uri가 없는경우 yaml에 registraion key로 CommonOAuth2Provider를 조회한다. 

     

    4. OAuth2LoginConfigurer 초기화 과정

    OAuth2LoginConfigurer는 기존 HttpSecurity, WebSecurity와 같이 SecurityBuilder를 상속받아 init(), configure()를 실행한다.

     

    init()단계에서 OAuth2LoginAuthenticationFilter는 Code를 AccessToken으로 교환

    configure()단계에서 OAuth2AuthorizationRequestRedirectFileter는 권한 부여 타입에서 Code를 받는 필터

    댓글

Designed by Tistory.