How to debug authentication problems in EWS?

Zdenek Devaty 0 Reputation points
2024-03-12T07:37:17.6266667+00:00

Hi, I am developing a booking integration for Microsoft Exchange Hybrid configuration. I'm using EWS, becasue Graph doesn't support hybrid. For development, I have an Exchange Online environment.

The ultimate goal is to access a list of rooms, list their events, create new events/bookings. So I start small and want to just list the rooms in the Exchange server.

So I created an app registration, generated client secret, added permissions like Calendars.ReadWrite, Directory.ReadAll to the app, and allowed impersonation.

But no matter what I do, I get "403 Forbidden". Can I get more detailed error message somewhere? How can I debug these problems?

Attaching my code to better describe what I'm trying to do.

type EWSHelper struct {
	Client *http.Client
	EwsUrl string
}

// NewEWSHelper initializes the EWSHelper with OAuth2 authentication and sets the EWS URL.
func NewEWSHelper(clientId, tenantId, clientSecret string) *EWSHelper {
	tokenURL := fmt.Sprintf("https://login.microsoftonline.com/%s/oauth2/v2.0/token", tenantId)
	ewsURL := "https://outlook.office365.com/EWS/Exchange.asmx"

	// Configure the OAuth2 client credentials flow
	config := clientcredentials.Config{
		ClientID:     clientId,
		ClientSecret: clientSecret,
		TokenURL:     tokenURL,
		Scopes:       []string{"https://outlook.office365.com/.default"},
	}

	ctx := context.Background()
	// Create an HTTP client using the OAuth2 config
	httpClient := config.Client(ctx)

	return &EWSHelper{
		Client: httpClient,
		EwsUrl: ewsURL,
	}
}

// GetRooms sends a SOAP request to EWS to get the list of room lists.
func (h *EWSHelper) GetRooms() error {
	requestBody := `
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
                  xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
    <soapenv:Header>
        <t:RequestServerVersion Version="Exchange2013_SP1"/>
        <t:ExchangeImpersonation>
            <t:ConnectingSID>
                <t:PrincipalName>app@z0vmd.onmicrosoft.com</t:PrincipalName>
            </t:ConnectingSID>
        </t:ExchangeImpersonation>
    </soapenv:Header>
    <soapenv:Body>
       <m:GetRooms/>
    </soapenv:Body>
</soapenv:Envelope>
`

	req, err := http.NewRequest("POST", h.EwsUrl, bytes.NewBufferString(requestBody))
	if err != nil {
		return fmt.Errorf("error creating request: %w", err)
	}

	// Set necessary headers, including Content-Type. Authorization is handled by the OAuth2 http client.
	req.Header.Add("Content-Type", "text/xml; charset=utf-8")

	req.Header.Add("X-AnchorMailbox", "app@z0vmd.onmicrosoft.com")

	resp, err := h.Client.Do(req)
	if err != nil {
		return fmt.Errorf("error sending request to EWS: %w", err)
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error reading response body: %w", err)
	}

	fmt.Printf("Status: %v\n", resp.Status)
	fmt.Printf("Response: %s\n", string(respBody))
	// Here, you would parse the XML response to extract the room lists.
	// For simplicity, this example prints the raw XML response.

	return nil
}

Microsoft Exchange Online
Microsoft Exchange Online Management
Microsoft Exchange Online Management
Microsoft Exchange Online: A Microsoft email and calendaring hosted service.Management: The act or process of organizing, handling, directing or controlling something.
4,208 questions
Exchange Server Development
Exchange Server Development
Exchange Server: A family of Microsoft client/server messaging and collaboration software.Development: The process of researching, productizing, and refining new or existing technologies.
516 questions
0 comments No comments
{count} votes