github.com/Axway/agent-sdk@v1.1.101/pkg/authz/oauth/mockidpserver.go (about)

     1  package oauth
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"net/url"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/google/uuid"
    14  )
    15  
    16  // MockIDPServer - interface for mock IDP server
    17  type MockIDPServer interface {
    18  	GetMetadataURL() string
    19  	GetIssuer() string
    20  	GetTokenURL() string
    21  	GetAuthEndpoint() string
    22  	GetRegistrationEndpoint() string
    23  	SetMetadataResponseCode(statusCode int)
    24  	SetTokenResponse(accessToken string, expiry time.Duration, statusCode int)
    25  	SetRegistrationResponseCode(statusCode int)
    26  	SetUseRegistrationAccessToken(useRegistrationAccessToken bool)
    27  	GetTokenRequestHeaders() http.Header
    28  	GetTokenQueryParams() url.Values
    29  	GetTokenRequestValues() url.Values
    30  	GetRequestHeaders() http.Header
    31  	GetQueryParams() url.Values
    32  	Close()
    33  }
    34  
    35  type mockIDPServer struct {
    36  	metadataResponseCode       int
    37  	tokenResponseCode          int
    38  	registerResponseCode       int
    39  	useRegistrationAccessToken bool
    40  	accessToken                string
    41  	tokenExpiry                time.Duration
    42  	serverMetadata             *AuthorizationServerMetadata
    43  	server                     *httptest.Server
    44  	tokenReqHeaders            http.Header
    45  	tokenQueryParams           url.Values
    46  	tokenReqValues             url.Values
    47  	reqHeaders                 http.Header
    48  	reqQueryParam              url.Values
    49  }
    50  
    51  // NewMockIDPServer - creates a new mock IDP server for tests
    52  func NewMockIDPServer() MockIDPServer {
    53  	m := &mockIDPServer{
    54  		metadataResponseCode: http.StatusOK,
    55  		tokenResponseCode:    http.StatusOK,
    56  		registerResponseCode: http.StatusCreated,
    57  	}
    58  
    59  	m.server = httptest.NewServer(http.HandlerFunc(m.handleRequest))
    60  	m.serverMetadata = &AuthorizationServerMetadata{
    61  		Issuer:                m.GetIssuer(),
    62  		TokenEndpoint:         m.GetTokenURL(),
    63  		AuthorizationEndpoint: m.GetAuthEndpoint(),
    64  		RegistrationEndpoint:  m.GetRegistrationEndpoint(),
    65  	}
    66  	return m
    67  }
    68  
    69  func (m *mockIDPServer) handleRequest(resp http.ResponseWriter, req *http.Request) {
    70  	if strings.Contains(req.RequestURI, "/metadata") {
    71  		defer func() {
    72  			m.metadataResponseCode = http.StatusOK
    73  		}()
    74  		if m.metadataResponseCode != http.StatusOK {
    75  			resp.WriteHeader(m.metadataResponseCode)
    76  
    77  			return
    78  		}
    79  		buf, _ := json.Marshal(m.serverMetadata)
    80  		resp.Write(buf)
    81  	}
    82  	if strings.Contains(req.RequestURI, "/token") {
    83  		m.tokenReqHeaders = req.Header
    84  		m.tokenQueryParams = req.URL.Query()
    85  		m.tokenReqValues = nil
    86  		reqBuf, _ := io.ReadAll(req.Body)
    87  		if len(reqBuf) != 0 {
    88  			fmt.Printf("%s\n", string(reqBuf))
    89  			val, err := url.ParseQuery(string(reqBuf))
    90  			if err == nil {
    91  				m.tokenReqValues = val
    92  			}
    93  		}
    94  		defer func() {
    95  			m.tokenResponseCode = http.StatusOK
    96  			m.accessToken = ""
    97  			m.tokenExpiry = 0
    98  		}()
    99  		if m.tokenResponseCode != http.StatusOK {
   100  			resp.WriteHeader(m.tokenResponseCode)
   101  			return
   102  		}
   103  
   104  		now := time.Now()
   105  		t := tokenResponse{
   106  			AccessToken: m.accessToken,
   107  			ExpiresIn:   now.Add(m.tokenExpiry).UnixNano() / 1e9,
   108  		}
   109  		buf, _ := json.Marshal(t)
   110  		resp.Write(buf)
   111  	}
   112  	if strings.Contains(req.RequestURI, "/register") {
   113  		m.reqHeaders = req.Header
   114  		m.reqQueryParam = req.URL.Query()
   115  		defer func() {
   116  			m.registerResponseCode = http.StatusCreated
   117  		}()
   118  		if req.Method == http.MethodPost {
   119  			if m.registerResponseCode != http.StatusCreated {
   120  				resp.WriteHeader(m.registerResponseCode)
   121  				return
   122  			}
   123  			resp.WriteHeader(http.StatusCreated)
   124  			clientBuf, _ := io.ReadAll(req.Body)
   125  			cl := &clientMetadata{}
   126  			json.Unmarshal(clientBuf, cl)
   127  			cl.ClientID = uuid.New().String()
   128  			cl.ClientSecret = uuid.New().String()
   129  			if m.useRegistrationAccessToken {
   130  				cl.RegistrationAccessToken = uuid.New().String()
   131  			}
   132  			clientBuf, _ = json.Marshal(cl)
   133  			resp.Write(clientBuf)
   134  		}
   135  		if req.Method == http.MethodDelete {
   136  			if m.registerResponseCode != http.StatusNoContent {
   137  				resp.WriteHeader(m.registerResponseCode)
   138  				return
   139  			}
   140  			resp.WriteHeader(http.StatusNoContent)
   141  		}
   142  	}
   143  }
   144  
   145  func (m *mockIDPServer) GetMetadataURL() string {
   146  	return m.server.URL + "/metadata"
   147  }
   148  
   149  func (m *mockIDPServer) GetIssuer() string {
   150  	return m.server.URL
   151  }
   152  
   153  func (m *mockIDPServer) GetTokenURL() string {
   154  	return m.server.URL + "/token"
   155  }
   156  
   157  func (m *mockIDPServer) GetAuthEndpoint() string {
   158  	return m.server.URL + "/auth"
   159  }
   160  
   161  func (m *mockIDPServer) GetRegistrationEndpoint() string {
   162  	return m.server.URL + "/register"
   163  }
   164  
   165  func (m *mockIDPServer) SetMetadataResponseCode(statusCode int) {
   166  	m.metadataResponseCode = statusCode
   167  }
   168  
   169  func (m *mockIDPServer) SetTokenResponse(accessToken string, expiry time.Duration, statusCode int) {
   170  	m.accessToken = accessToken
   171  	m.tokenExpiry = expiry
   172  	m.tokenResponseCode = statusCode
   173  }
   174  
   175  func (m *mockIDPServer) SetRegistrationResponseCode(statusCode int) {
   176  	m.registerResponseCode = statusCode
   177  }
   178  
   179  func (m *mockIDPServer) SetUseRegistrationAccessToken(useRegistrationAccessToken bool) {
   180  	m.useRegistrationAccessToken = useRegistrationAccessToken
   181  }
   182  
   183  func (m *mockIDPServer) GetTokenRequestHeaders() http.Header {
   184  	return m.tokenReqHeaders
   185  }
   186  
   187  func (m *mockIDPServer) GetTokenQueryParams() url.Values {
   188  	return m.tokenQueryParams
   189  }
   190  
   191  func (m *mockIDPServer) GetTokenRequestValues() url.Values {
   192  	return m.tokenReqValues
   193  }
   194  
   195  func (m *mockIDPServer) GetRequestHeaders() http.Header {
   196  	return m.reqHeaders
   197  }
   198  
   199  func (m *mockIDPServer) GetQueryParams() url.Values {
   200  	return m.reqQueryParam
   201  }
   202  func (m *mockIDPServer) Close() {
   203  	m.server.Close()
   204  }