In oauth you make a request using you client id/secret to get an authorization code.
Authorization code request does not contain the client secret. It only contain the client ID and redirect url, which enable authorization server to validate the request to originate from a known client.
What is this two step process required instead of getting access token in the first place? How does it make the whole process more secure? Or is there another reason.
If we forget about implicit flow, which involves retrieving access token from first call, I would say it is to improve security.
When authorization code flow is used, you use a user agent (browser) to initiate the flow. This means, the user agent will redirect end user to authorization server for authentication (username password obtaining and validating end user). If end user validation succeed, authorization server sends the authorization code. This is a temporary secret, which is bound to original authorization code request.
Now client use the authorization code and directly contact authorization server to obtain access (and other) tokens. This second step occur outside the user agent.
If the client is a confidential client, a client which has a client ID as well as a client secret, this second call will require to produce this client secret. So it internally contain a client validation process. From authorization server perspective, token request will be rejected if client authentication failed. This gives protection for authorization code stealing.
Also, with the second step, we avoid access token exposure to third party. For example, in implicit flow, access token is sent as URL fragments through user agent. If user agent is compromised (ex:- Manipulated by some malicious code) this access token can be extracted.
What about public clients ? That means clients which does not get a client secret due to their nature (ex:- Clients which cannot protect the secret by storing)
Public clients use PKCE. It is a must to use this to avoid authorization code stealing. So in the token request (second call), client will directly send code verifier. User agent cannot obtain code verifier in the first request since it was hashed (code challenge). So token request now contains a secret that only known by client and authorization server.
If you compare both scenarios (public and confidential clients), you can see how the second call adds an extra layer of security.