Redirecting the user back to the application by returning_url, as part of the OAuth2 protocol

318 Views Asked by At

Used backend on spring boot, frontend on angular and web server on nginx.

when a user selects an authorization method through a third-party service when entering the site, he is redirected to this service, where he enters his login and password, after which this service provides the requested data for the user. At this moment, he must be redirected back to the site and he should be in his personal account.

how to implement the return_url so that the user appears correctly on my site, then, from the URL browser line, it was possible to read the authorization code provided by the third-party service, adding to my redirect_url?

I made such a controller in spring boot:

@RestController
@RequestMapping("/callback/")
public class ServiceReturnController {

    @GetMapping(path = "service_return", produces = "text/plain")
    public ResponseEntity<?> handleReturn(
            @RequestParam(name = "code", required = false) String authCode,
            @RequestParam(name = "error", required = false) String error,
            @RequestParam(name = "error_description", required = false) String errorDescription
    ) {
        StringJoiner joiner = new StringJoiner("\n\n");
        if (StringUtils.hasText(error)) {
            joiner.add("error=" + error);

        }
        if (StringUtils.hasText(errorDescription)) {
            joiner.add("error_description=" + errorDescription);
        }

        if (joiner.length() != 0) {
            joiner.add("No expected parameters received.");
            return ResponseEntity.ok().body(joiner.toString());
        }
        return ResponseEntity.ok().build();
    }
}

I make retun_url like this: https://exampleMyApp.com/callback/service_return

My config nginx, here is the route to my controller in spring boot:

location /callback/{
proxy_pass http://exampleMyApp-API.ru:9089/callback/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 500m;
}

After successful authentication, the user should be in the personal account of my site. But for this, the frontend must read the authorization code from the URL and make another request to get an access token and visit the site with it

URL: http://exampleMyApp.com/callback/service_return?code=eyJ2ZXIiOjEsInR5cCI6IkpXVCIsInNidCI6ImF1dGhvcml6&state=wvwwvw-wevwvw-wew

how it's done ? maybe I have some flaws. Advise how to redirect to the site and perform an additional request after validating the access token.

1

There are 1 best solutions below

0
forbiddencoding On

You can access query parameters on your current route by subscribing to the ActivatedRoute. With params.get(<PARAM_NAME>) you get the parameters string value or undefined.

Make a call to your backend with the code and state received. On your backend check the state and exchange the code for an access token.

Send a response to your frontend, depending of the outcome of the code exchange.

Angular Code:

import {ActivatedRoute} from '@angular/router'
import {exhaustMap, noop, switchMap, take} from "rxjs";
....

@Component({
    selector: 'app-callback',
    ...
})
export class CallbackComponent {
    
    constructor(
        private readonly route: ActivatedRoute,
        // your serivce for calling your backend
        private readonly exchangeService: ExchangeService
    ) {
        // get the current route params
        void route.queryParams.pipe(
            switchMap((params: Params)) => {
                // get the code
                const code = params.get('code')
                // get the state
                const state = params.get('state')

                // exchange the code for a token on your backend
                return this.exchangeService.exchangeCode(code, state).pipe(
                    exhaustMap(result => {
                        // handle your backend response here
                        ...
                    })
                )
            }),
            take(1)
        ).subscribe(noop)
    }
}